Skip to content

Commit 2f7269b

Browse files
committed
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
1 parent b78b984 commit 2f7269b

File tree

5 files changed

+44
-1
lines changed

5 files changed

+44
-1
lines changed

clang/include/clang/Basic/TokenKinds.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,9 @@ ANNOTATION(non_type_undeclared) // annotation for an undeclared identifier that
742742
ANNOTATION(non_type_dependent) // annotation for an assumed non-type member of
743743
// a dependent base class
744744
ANNOTATION(primary_expr) // annotation for a primary expression
745+
ANNOTATION(
746+
uneval_primary_expr) // annotation for a primary expression which should be
747+
// transformed to potentially evaluated
745748
ANNOTATION(decltype) // annotation for a decltype expression,
746749
// e.g., "decltype(foo.bar())"
747750

clang/lib/Parse/ParseExpr.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,8 +998,23 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
998998
Diag(Tok, diag::warn_cxx98_compat_nullptr);
999999
return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
10001000

1001+
case tok::annot_uneval_primary_expr:
10011002
case tok::annot_primary_expr:
10021003
Res = getExprAnnotation(Tok);
1004+
if (SavedKind == tok::annot_uneval_primary_expr) {
1005+
if (Expr *E = Res.get()) {
1006+
if (!E->isTypeDependent() && !E->containsErrors()) {
1007+
// TransformToPotentiallyEvaluated expects that it will still be in a
1008+
// (temporary) unevaluated context and then looks through that context
1009+
// to build it in the surrounding context. So we need to push an
1010+
// unevaluated context to balance things out.
1011+
EnterExpressionEvaluationContext Unevaluated(
1012+
Actions, Sema::ExpressionEvaluationContext::Unevaluated,
1013+
Sema::ReuseLambdaContextDecl);
1014+
Res = Actions.TransformToPotentiallyEvaluated(Res.get());
1015+
}
1016+
}
1017+
}
10031018
ConsumeAnnotationToken();
10041019
if (!Res.isInvalid() && Tok.is(tok::less))
10051020
checkPotentialAngleBracket(Res);

clang/lib/Parse/ParseTentative.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,15 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
12751275
// this is ambiguous. Typo-correct to type and expression keywords and
12761276
// to types and identifiers, in order to try to recover from errors.
12771277
TentativeParseCCC CCC(Next);
1278+
// Tentative parsing may not be done in the right evaluation context
1279+
// for the ultimate expression. Enter an unevaluated context to prevent
1280+
// Sema from immediately e.g. treating this lookup as a potential ODR-use.
1281+
// If we generate an expression annotation token and the parser actually
1282+
// claims it as an expression, we'll transform the expression to a
1283+
// potentially-evaluated one then.
1284+
EnterExpressionEvaluationContext Unevaluated(
1285+
Actions, Sema::ExpressionEvaluationContext::Unevaluated,
1286+
Sema::ReuseLambdaContextDecl);
12781287
switch (TryAnnotateName(&CCC)) {
12791288
case ANK_Error:
12801289
return TPResult::Error;

clang/lib/Parse/Parser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1694,7 +1694,8 @@ Parser::TryAnnotateName(CorrectionCandidateCallback *CCC) {
16941694
}
16951695

16961696
case Sema::NC_ContextIndependentExpr:
1697-
Tok.setKind(tok::annot_primary_expr);
1697+
Tok.setKind(Actions.isUnevaluatedContext() ? tok::annot_uneval_primary_expr
1698+
: tok::annot_primary_expr);
16981699
setExprAnnotation(Tok, Classification.getExpression());
16991700
Tok.setAnnotationEndLoc(NameLoc);
17001701
if (SS.isNotEmpty())
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clang_cc1 -fsyntax-only %s -ast-dump | FileCheck %s
2+
3+
struct FOO {
4+
static const int vec_align_bytes = 32;
5+
void foo() {
6+
double a alignas(vec_align_bytes);
7+
;
8+
}
9+
};
10+
11+
// CHECK: AlignedAttr {{.*}} alignas
12+
// CHECK: ConstantExpr {{.+}} 'int' Int: 32
13+
// CHECK: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
14+
// CHECK: DeclRefExpr {{.*}} 'const int' lvalue Var {{.*}} 'vec_align_bytes' 'const int' non_odr_use_constant
15+
// CHECK: NullStmt

0 commit comments

Comments
 (0)