Skip to content

Commit

Permalink
[clang] Do not crash after suggesting typo correction to constexpr if…
Browse files Browse the repository at this point in the history
… condition

In some cases non-null non-constant yet valid expression may reach point where
`ConditionResult` is created. For example, typo correction mechanism can return
such expression, so double check before evaluating it.

Fixes #61885

Reviewed By: tbaeder, aaron.ballman

Differential Revision: https://reviews.llvm.org/D148206
  • Loading branch information
Fznamznon committed Apr 17, 2023
1 parent 3e38187 commit 9d9046f
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 13 deletions.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ Bug Fixes in This Version
bit-fields. This fixes:
(`#61355 <https://github.com/llvm/llvm-project/issues/61335>`_) and
(`#61417 <https://github.com/llvm/llvm-project/issues/61417>`_)
- Fix crash after suggesting typo correction to constexpr if condition.
(`#61885 <https://github.com/llvm/llvm-project/issues/61885>`_)

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
24 changes: 11 additions & 13 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -12843,20 +12843,22 @@ class Sema final {
Decl *ConditionVar;
FullExprArg Condition;
bool Invalid;
bool HasKnownValue;
bool KnownValue;
std::optional<bool> KnownValue;

friend class Sema;
ConditionResult(Sema &S, Decl *ConditionVar, FullExprArg Condition,
bool IsConstexpr)
: ConditionVar(ConditionVar), Condition(Condition), Invalid(false),
HasKnownValue(IsConstexpr && Condition.get() &&
!Condition.get()->isValueDependent()),
KnownValue(HasKnownValue &&
!!Condition.get()->EvaluateKnownConstInt(S.Context)) {}
: ConditionVar(ConditionVar), Condition(Condition), Invalid(false) {
if (IsConstexpr && Condition.get()) {
if (std::optional<llvm::APSInt> Val =
Condition.get()->getIntegerConstantExpr(S.Context)) {
KnownValue = !!(*Val);
}
}
}
explicit ConditionResult(bool Invalid)
: ConditionVar(nullptr), Condition(nullptr), Invalid(Invalid),
HasKnownValue(false), KnownValue(false) {}
KnownValue(std::nullopt) {}

public:
ConditionResult() : ConditionResult(false) {}
Expand All @@ -12865,11 +12867,7 @@ class Sema final {
return std::make_pair(cast_or_null<VarDecl>(ConditionVar),
Condition.get());
}
std::optional<bool> getKnownValue() const {
if (!HasKnownValue)
return std::nullopt;
return KnownValue;
}
std::optional<bool> getKnownValue() const { return KnownValue; }
};
static ConditionResult ConditionError() { return ConditionResult(true); }

Expand Down
14 changes: 14 additions & 0 deletions clang/test/SemaCXX/invalid-if-constexpr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %clang_cc1 -verify -std=c++20 %s

namespace GH61885 {
void similar() { // expected-note {{'similar' declared here}}
if constexpr (similer<>) {} // expected-error {{use of undeclared identifier 'similer'; did you mean 'similar'?}}
}
void a() { if constexpr (__adl_swap<>) {}} // expected-error{{use of undeclared identifier '__adl_swap'; did you mean '__sync_swap'?}} \
// expected-note {{'__sync_swap' declared here}}

int AA() { return true;} // expected-note {{'AA' declared here}}

void b() { if constexpr (AAA<>) {}} // expected-error {{use of undeclared identifier 'AAA'; did you mean 'AA'?}}
}

0 comments on commit 9d9046f

Please sign in to comment.