[PATCH] D80925: Fix compiler crash when an expression parsed in the tentative parsing and must be claimed in the another evaluation context.

Alexey Bataev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 2 10:25:52 PDT 2020


ABataev updated this revision to Diff 267927.
ABataev added a comment.

Rebase + fixes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80925/new/

https://reviews.llvm.org/D80925

Files:
  clang/include/clang/Basic/TokenKinds.def
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Parse/ParseTentative.cpp
  clang/lib/Parse/Parser.cpp
  clang/test/AST/alignas_maybe_odr_cleanup.cpp


Index: clang/test/AST/alignas_maybe_odr_cleanup.cpp
===================================================================
--- /dev/null
+++ 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
Index: clang/lib/Parse/Parser.cpp
===================================================================
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -1694,7 +1694,8 @@
   }
 
   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())
Index: clang/lib/Parse/ParseTentative.cpp
===================================================================
--- clang/lib/Parse/ParseTentative.cpp
+++ clang/lib/Parse/ParseTentative.cpp
@@ -1275,6 +1275,15 @@
       // 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;
Index: clang/lib/Parse/ParseExpr.cpp
===================================================================
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -998,8 +998,23 @@
     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);
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -742,6 +742,9 @@
 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())"
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D80925.267927.patch
Type: text/x-patch
Size: 4288 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200602/551b3b73/attachment.bin>


More information about the cfe-commits mailing list