[cfe-commits] r148610 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Parse/ParseDecl.cpp lib/Parse/ParseExpr.cpp lib/Sema/AnalysisBasedWarnings.cpp lib/Sema/SemaExpr.cpp test/Sema/i-c-e.c test/Sema/vla-2.c test/SemaCXX/vararg-non-pod.cpp
Eli Friedman
eli.friedman at gmail.com
Fri Jan 20 17:01:52 PST 2012
Author: efriedma
Date: Fri Jan 20 19:01:51 2012
New Revision: 148610
URL: http://llvm.org/viewvc/llvm-project?rev=148610&view=rev
Log:
Make clang's AST model sizeof and typeof with potentially-evaluated operands correctly, similar to what we already do with typeid.
Added:
cfe/trunk/test/Sema/vla-2.c
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/Sema/i-c-e.c
cfe/trunk/test/SemaCXX/vararg-non-pod.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=148610&r1=148609&r2=148610&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jan 20 19:01:51 2012
@@ -2256,6 +2256,7 @@
void DiscardCleanupsInEvaluationContext();
ExprResult TranformToPotentiallyEvaluated(Expr *E);
+ ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=148610&r1=148609&r2=148610&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Jan 20 19:01:51 2012
@@ -4607,10 +4607,13 @@
// Parse the constant-expression or assignment-expression now (depending
// on dialect).
- if (getLang().CPlusPlus)
+ if (getLang().CPlusPlus) {
NumElements = ParseConstantExpression();
- else
+ } else {
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Sema::ConstantEvaluated);
NumElements = ParseAssignmentExpression();
+ }
}
// If there was an error parsing the assignment-expression, recover.
@@ -4647,6 +4650,8 @@
const bool hasParens = Tok.is(tok::l_paren);
+ EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+
bool isCastExpr;
ParsedType CastTy;
SourceRange CastRange;
@@ -4682,6 +4687,13 @@
return;
}
+ // We might need to transform the operand if it is potentially evaluated.
+ Operand = Actions.HandleExprEvaluationContextForTypeof(Operand.get());
+ if (Operand.isInvalid()) {
+ DS.SetTypeSpecError();
+ return;
+ }
+
const char *PrevSpec = 0;
unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=148610&r1=148609&r2=148610&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Jan 20 19:01:51 2012
@@ -1442,14 +1442,6 @@
return ExprError();
}
- // C++0x [expr.sizeof]p1:
- // [...] The operand is either an expression, which is an unevaluated
- // operand (Clause 5) [...]
- //
- // The GNU typeof and GNU/C++11 alignof extensions also behave as
- // unevaluated operands.
- EnterExpressionEvaluationContext Unevaluated(Actions,
- Sema::Unevaluated);
Operand = ParseCastExpression(true/*isUnaryExpression*/);
} else {
// If it starts with a '(', we know that it is either a parenthesized
@@ -1459,14 +1451,6 @@
ParenParseOption ExprType = CastExpr;
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
- // C++0x [expr.sizeof]p1:
- // [...] The operand is either an expression, which is an unevaluated
- // operand (Clause 5) [...]
- //
- // The GNU typeof and GNU/C++11 alignof extensions also behave as
- // unevaluated operands.
- EnterExpressionEvaluationContext Unevaluated(Actions,
- Sema::Unevaluated);
Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
false, CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
@@ -1555,6 +1539,8 @@
if (OpTok.is(tok::kw_alignof))
Diag(OpTok, diag::warn_cxx98_compat_alignof);
+ EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
+
bool isCastExpr;
ParsedType CastTy;
SourceRange CastRange;
Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=148610&r1=148609&r2=148610&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Fri Jan 20 19:01:51 2012
@@ -849,8 +849,12 @@
bool processed = false;
if (const Stmt *stmt = i->stmt) {
const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt);
- assert(block);
- if (CFGReverseBlockReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) {
+ CFGReverseBlockReachabilityAnalysis *cra =
+ AC.getCFGReachablityAnalysis();
+ // FIXME: We should be able to assert that block is non-null, but
+ // the CFG analysis can skip potentially-evaluated expressions in
+ // edge cases; see test/Sema/vla-2.c.
+ if (block && cra) {
// Can this block be reached from the entrance?
if (cra->isReachable(&AC.getCFG()->getEntry(), block))
S.Diag(D.Loc, D.PD);
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=148610&r1=148609&r2=148610&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Jan 20 19:01:51 2012
@@ -3012,6 +3012,12 @@
if (isInvalid)
return ExprError();
+ if (ExprKind == UETT_SizeOf && E->getType()->isVariableArrayType()) {
+ PE = TranformToPotentiallyEvaluated(E);
+ if (PE.isInvalid()) return ExprError();
+ E = PE.take();
+ }
+
// C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
return Owned(new (Context) UnaryExprOrTypeTraitExpr(
ExprKind, E, Context.getSizeType(), OpLoc,
@@ -9435,6 +9441,12 @@
ExprNeedsCleanups = false;
}
+ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) {
+ if (!E->getType()->isVariablyModifiedType())
+ return E;
+ return TranformToPotentiallyEvaluated(E);
+}
+
/// \brief Note that the given declaration was referenced in the source code.
///
/// This routine should be invoke whenever a given declaration is referenced
Modified: cfe/trunk/test/Sema/i-c-e.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/i-c-e.c?rev=148610&r1=148609&r2=148610&view=diff
==============================================================================
--- cfe/trunk/test/Sema/i-c-e.c (original)
+++ cfe/trunk/test/Sema/i-c-e.c Fri Jan 20 19:01:51 2012
@@ -54,24 +54,21 @@
char z[__builtin_constant_p(4) ? 1 : -1];
// Comma tests
-int comma1[0?1,2:3]; // expected-warning {{expression result unused}}
-int comma2[1||(1,2)]; // expected-warning {{expression result unused}} \
- // expected-warning {{use of logical '||' with constant operand}} \
+int comma1[0?1,2:3];
+int comma2[1||(1,2)]; // expected-warning {{use of logical '||' with constant operand}} \
// expected-note {{use '|' for a bitwise operation}}
-int comma3[(1,2)]; // expected-warning {{size of static array must be an integer constant expression}} \
- // expected-warning {{expression result unused}}
+int comma3[(1,2)]; // expected-warning {{size of static array must be an integer constant expression}}
// Pointer + __builtin_constant_p
char pbcp[__builtin_constant_p(4) ? (intptr_t)&expr : 0]; // expected-error {{variable length array declaration not allowed at file scope}}
-int illegaldiv1a[1 || 1/0]; // expected-warning {{division by zero is undefined}}
-int illegaldiv1b[1 && 1/0]; // expected-warning {{division by zero is undefined}} expected-error{{variable length array declaration not allowed at file scope}}
+int illegaldiv1a[1 || 1/0];
+int illegaldiv1b[1 && 1/0]; //expected-error{{variable length array declaration not allowed at file scope}}
-int illegaldiv2[1/0]; // expected-error {{variable length array declaration not allowed at file scope}} \
- // expected-warning {{division by zero is undefined}}
+int illegaldiv2[1/0]; // expected-error {{variable length array declaration not allowed at file scope}}
int illegaldiv3[INT_MIN / -1]; // expected-error {{variable length array declaration not allowed at file scope}}
// PR9262
-int illegaldiv4[0 / (1 / 0)]; // expected-warning {{division by zero is undefined}} expected-error {{variable length array declaration not allowed at file scope}}
+int illegaldiv4[0 / (1 / 0)]; // expected-error {{variable length array declaration not allowed at file scope}}
int chooseexpr[__builtin_choose_expr(1, 1, expr)];
int realop[(__real__ 4) == 4 ? 1 : -1];
Added: cfe/trunk/test/Sema/vla-2.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/vla-2.c?rev=148610&view=auto
==============================================================================
--- cfe/trunk/test/Sema/vla-2.c (added)
+++ cfe/trunk/test/Sema/vla-2.c Fri Jan 20 19:01:51 2012
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only -pedantic
+// Check that we don't crash trying to emit warnings in a potentially-evaluated
+// sizeof or typeof. (This test needs to be in a separate file because we use
+// a different codepath when we have already emitted an error.)
+
+int PotentiallyEvaluatedSizeofWarn(int n) {
+ return (int)sizeof *(0 << 32,(int(*)[n])0); // expected-warning {{expression result unused}} expected-warning {{shift count >= width of type}}
+}
+
+void PotentiallyEvaluatedTypeofWarn(int n) {
+ __typeof(*(0 << 32,(int(*)[n])0)) x; // expected-warning {{expression result unused}} expected-warning {{shift count >= width of type}}
+ (void)x;
+}
+
+void PotentiallyEvaluatedArrayBoundWarn(int n) {
+ (void)*(int(*)[(0 << 32,n)])0; // FIXME: We should warn here.
+}
Modified: cfe/trunk/test/SemaCXX/vararg-non-pod.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/vararg-non-pod.cpp?rev=148610&r1=148609&r2=148610&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/vararg-non-pod.cpp (original)
+++ cfe/trunk/test/SemaCXX/vararg-non-pod.cpp Fri Jan 20 19:01:51 2012
@@ -118,3 +118,8 @@
(void)__builtin_va_arg(list, Abstract); // expected-error{{second argument to 'va_arg' is of abstract type 'Abstract'}}
__builtin_va_end(list);
}
+
+int t9(int n) {
+ // Make sure the error works in potentially-evaluated sizeof
+ return (int)sizeof(*(Helper(Foo()), (int (*)[n])0)); // expected-warning{{cannot pass object of non-POD type}}
+}
More information about the cfe-commits
mailing list