[clang] 2f7269b - Fix compiler crash when an expression parsed in the tentative parsing and must be claimed in the another evaluation context.
Alexey Bataev via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 2 11:46:09 PDT 2020
Author: Alexey Bataev
Date: 2020-06-02T14:27:33-04:00
New Revision: 2f7269b6773de2750f9cd1417ef5f21cd6cf7a91
URL: https://github.com/llvm/llvm-project/commit/2f7269b6773de2750f9cd1417ef5f21cd6cf7a91
DIFF: https://github.com/llvm/llvm-project/commit/2f7269b6773de2750f9cd1417ef5f21cd6cf7a91.diff
LOG: Fix compiler crash when an expression parsed in the tentative parsing and must be claimed in the another evaluation context.
Summary:
Clang crashes when trying to finish function body. MaybeODRUseExprs is
not empty because of const static data member parsed in outer evaluation
context, upon call for isTypeIdInParens() function. It builds
annot_primary_expr, later parsed in ParseConstantExpression() in
inner constant expression evaluation context.
Reviewers: rjmccall, rsmith
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D80925
Added:
clang/test/AST/alignas_maybe_odr_cleanup.cpp
Modified:
clang/include/clang/Basic/TokenKinds.def
clang/lib/Parse/ParseExpr.cpp
clang/lib/Parse/ParseTentative.cpp
clang/lib/Parse/Parser.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 919c51f0e41d..876f53c84ee0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -742,6 +742,9 @@ ANNOTATION(non_type_undeclared) // annotation for an undeclared identifier that
ANNOTATION(non_type_dependent) // annotation for an assumed non-type member of
// a dependent base class
ANNOTATION(primary_expr) // annotation for a primary expression
+ANNOTATION(
+ uneval_primary_expr) // annotation for a primary expression which should be
+ // transformed to potentially evaluated
ANNOTATION(decltype) // annotation for a decltype expression,
// e.g., "decltype(foo.bar())"
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 544fe6123677..1ef352eb5c27 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -998,8 +998,23 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
Diag(Tok, diag::warn_cxx98_compat_nullptr);
return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
+ case tok::annot_uneval_primary_expr:
case tok::annot_primary_expr:
Res = getExprAnnotation(Tok);
+ if (SavedKind == tok::annot_uneval_primary_expr) {
+ if (Expr *E = Res.get()) {
+ if (!E->isTypeDependent() && !E->containsErrors()) {
+ // TransformToPotentiallyEvaluated expects that it will still be in a
+ // (temporary) unevaluated context and then looks through that context
+ // to build it in the surrounding context. So we need to push an
+ // unevaluated context to balance things out.
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated,
+ Sema::ReuseLambdaContextDecl);
+ Res = Actions.TransformToPotentiallyEvaluated(Res.get());
+ }
+ }
+ }
ConsumeAnnotationToken();
if (!Res.isInvalid() && Tok.is(tok::less))
checkPotentialAngleBracket(Res);
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index ff941cfc441d..9179cc91cfe7 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1275,6 +1275,15 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// this is ambiguous. Typo-correct to type and expression keywords and
// to types and identifiers, in order to try to recover from errors.
TentativeParseCCC CCC(Next);
+ // Tentative parsing may not be done in the right evaluation context
+ // for the ultimate expression. Enter an unevaluated context to prevent
+ // Sema from immediately e.g. treating this lookup as a potential ODR-use.
+ // If we generate an expression annotation token and the parser actually
+ // claims it as an expression, we'll transform the expression to a
+ // potentially-evaluated one then.
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated,
+ Sema::ReuseLambdaContextDecl);
switch (TryAnnotateName(&CCC)) {
case ANK_Error:
return TPResult::Error;
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index de809b9ee849..2cea7307b3ac 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1694,7 +1694,8 @@ Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) {
}
case Sema::NC_ContextIndependentExpr:
- Tok.setKind(tok::annot_primary_expr);
+ Tok.setKind(Actions.isUnevaluatedContext() ? tok::annot_uneval_primary_expr
+ : tok::annot_primary_expr);
setExprAnnotation(Tok, Classification.getExpression());
Tok.setAnnotationEndLoc(NameLoc);
if (SS.isNotEmpty())
diff --git a/clang/test/AST/alignas_maybe_odr_cleanup.cpp b/clang/test/AST/alignas_maybe_odr_cleanup.cpp
new file mode 100644
index 000000000000..ebc09084528e
--- /dev/null
+++ b/clang/test/AST/alignas_maybe_odr_cleanup.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only %s -ast-dump | FileCheck %s
+
+struct FOO {
+ static const int vec_align_bytes = 32;
+ void foo() {
+ double a alignas(vec_align_bytes);
+ ;
+ }
+};
+
+// CHECK: AlignedAttr {{.*}} alignas
+// CHECK: ConstantExpr {{.+}} 'int' Int: 32
+// CHECK: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
+// CHECK: DeclRefExpr {{.*}} 'const int' lvalue Var {{.*}} 'vec_align_bytes' 'const int' non_odr_use_constant
+// CHECK: NullStmt
More information about the cfe-commits
mailing list