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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits