diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def --- a/clang/include/clang/Basic/TokenKinds.def +++ b/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())" diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -998,8 +998,19 @@ 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()) { + 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 --- a/clang/lib/Parse/ParseTentative.cpp +++ b/clang/lib/Parse/ParseTentative.cpp @@ -1275,6 +1275,11 @@ // 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); + // Enter unevaluated context to prevent propagation of the odr-use data to + // outer context in case of unsuccesful tentative parsing. + 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 --- a/clang/lib/Parse/Parser.cpp +++ b/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()) diff --git a/clang/test/AST/alignas_maybe_odr_cleanup.cpp b/clang/test/AST/alignas_maybe_odr_cleanup.cpp new file mode 100644 --- /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' +// CHECK: DeclRefExpr {{.*}} 'const int' lvalue Var {{.*}} 'vec_align_bytes' 'const int' non_odr_use_constant +// CHECK: NullStmt