]> granicus.if.org Git - clang/commitdiff
vla expressions used in __typeof__ must be evaluated.
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 28 Sep 2010 20:42:35 +0000 (20:42 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 28 Sep 2010 20:42:35 +0000 (20:42 +0000)
Fixes rdar://8476159.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114982 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseStmt.cpp
lib/Parse/Parser.cpp
lib/Sema/SemaDecl.cpp
test/CodeGen/vla.c

index 11f4be7cc34fe22b24af4bf22bde809180ea93b8..f8db30af5bbd50198b619ada28111c7bbd2f2a85 100644 (file)
@@ -1137,9 +1137,11 @@ private:
   // C99 6.8: Statements and Blocks.
 
   StmtResult ParseStatement() {
-    return ParseStatementOrDeclaration(true);
+    StmtVector Stmts(Actions);
+    return ParseStatementOrDeclaration(Stmts, true);
   }
-  StmtResult ParseStatementOrDeclaration(bool OnlyStatement = false);
+  StmtResult ParseStatementOrDeclaration(StmtVector& Stmts,
+                                         bool OnlyStatement = false);
   StmtResult ParseLabeledStatement(AttributeList *Attr);
   StmtResult ParseCaseStatement(AttributeList *Attr);
   StmtResult ParseDefaultStatement(AttributeList *Attr);
@@ -1193,9 +1195,11 @@ private:
     DSC_top_level // top-level/namespace declaration context
   };
 
-  DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd,
+  DeclGroupPtrTy ParseDeclaration(StmtVector &Stmts,
+                                  unsigned Context, SourceLocation &DeclEnd,
                                   CXX0XAttributeList Attr);
-  DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
+  DeclGroupPtrTy ParseSimpleDeclaration(StmtVector &Stmts,
+                                        unsigned Context,
                                         SourceLocation &DeclEnd,
                                         AttributeList *Attr,
                                         bool RequireSemi);
index dcbf3dc2ca6a18acab5a567f5f79f4bcd3b56256..85701cd78f1a3b88311b3a0c73d765b70b2d43a7 100644 (file)
@@ -761,6 +761,8 @@ public:
   /// no declarator (e.g. "struct foo;") is parsed.
   Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
                                    DeclSpec &DS);
+  
+  StmtResult ActOnVlaStmt(const DeclSpec &DS);
 
   Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
                                     AccessSpecifier AS,
index 5ed22e275377ecab78e405c4c375ed428cf2674d..0a48d4d550777501630d4dcf8d569117607399dd 100644 (file)
@@ -320,7 +320,8 @@ AttributeList* Parser::ParseBorlandTypeAttributes(AttributeList *CurrAttr) {
 /// [C++0x] static_assert-declaration
 ///         others... [FIXME]
 ///
-Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
+Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts,
+                                                unsigned Context,
                                                 SourceLocation &DeclEnd,
                                                 CXX0XAttributeList Attr) {
   ParenBraceBracketBalancer BalancerRAIIObj(*this);
@@ -344,7 +345,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
       SingleDecl = ParseNamespace(Context, DeclEnd, InlineLoc);
       break;
     }
-    return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList, true);
+    return ParseSimpleDeclaration(Stmts, Context, DeclEnd, Attr.AttrList, 
+                                  true);
   case tok::kw_namespace:
     if (Attr.HasAttr)
       Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
@@ -361,7 +363,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
     SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
     break;
   default:
-    return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList, true);
+    return ParseSimpleDeclaration(Stmts, Context, DeclEnd, Attr.AttrList, 
+                                  true);
   }
   
   // This routine returns a DeclGroup, if the thing we parsed only contains a
@@ -376,7 +379,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
 ///
 /// If RequireSemi is false, this does not check for a ';' at the end of the
 /// declaration.  If it is true, it checks for and eats it.
-Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
+Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts, 
+                                                      unsigned Context,
                                                       SourceLocation &DeclEnd,
                                                       AttributeList *Attr,
                                                       bool RequireSemi) {
@@ -386,6 +390,9 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
     DS.AddAttributes(Attr);
   ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
                             getDeclSpecContextFromDeclaratorContext(Context));
+  StmtResult R = Actions.ActOnVlaStmt(DS);
+  if (R.isUsable())
+    Stmts.push_back(R.release());
 
   // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
   // declaration-specifiers init-declarator-list[opt] ';'
index d4523d226ad4fe03f141fe65cd57b145aa11aed6..d340d574d4d29f4f3f6ebb187c9acc20c3bc9cff 100644 (file)
@@ -75,7 +75,7 @@ using namespace clang;
 /// [OBC]   '@' 'throw' ';'
 ///
 StmtResult
-Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
+Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) {
   const char *SemiError = 0;
   StmtResult Res;
   
@@ -101,7 +101,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
   case tok::code_completion:
     Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement);
     ConsumeCodeCompletionToken();
-    return ParseStatementOrDeclaration(OnlyStatement);
+    return ParseStatementOrDeclaration(Stmts, OnlyStatement);
       
   case tok::identifier:
     if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
@@ -114,7 +114,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
     if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
       AttrList.take(); //Passing 'Attr' to ParseDeclaration transfers ownership.
-      DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+      DeclGroupPtrTy Decl = ParseDeclaration(Stmts, Declarator::BlockContext, DeclEnd,
                                              Attr);
       return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
     }
@@ -466,12 +466,11 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
   // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension.  These are
   // only allowed at the start of a compound stmt regardless of the language.
 
-  typedef StmtVector StmtsTy;
-  StmtsTy Stmts(Actions);
+  StmtVector Stmts(Actions);
   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
     StmtResult R;
     if (Tok.isNot(tok::kw___extension__)) {
-      R = ParseStatementOrDeclaration(false);
+      R = ParseStatementOrDeclaration(Stmts, false);
     } else {
       // __extension__ can start declarations and it can also be a unary
       // operator for expressions.  Consume multiple __extension__ markers here
@@ -492,7 +491,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
         ExtensionRAIIObject O(Diags);
 
         SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
-        DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
+        DeclGroupPtrTy Res = ParseDeclaration(Stmts,
+                                              Declarator::BlockContext, DeclEnd,
                                               Attr);
         R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
       } else {
@@ -1015,8 +1015,9 @@ StmtResult Parser::ParseForStatement(AttributeList *Attr) {
       AttrList = ParseCXX0XAttributes().AttrList;
 
     SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
-    DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
-                                               AttrList, false);
+    StmtVector Stmts(Actions);
+    DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, 
+                                               DeclEnd, AttrList, false);
     FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
 
     if (Tok.is(tok::semi)) {  // for (int x = 4;
index cd4f342042b6a65c0f10532875db0aa6c3a16609..33c7b7dcb4c50e9b0d423f9961fc5273a39d0c7e 100644 (file)
@@ -519,14 +519,16 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr,
     // A function definition cannot start with a these keywords.
     {
       SourceLocation DeclEnd;
-      return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
+      StmtVector Stmts(Actions);
+      return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, Attr);
     }
 
   case tok::kw_inline:
     if (getLang().CPlusPlus && NextToken().is(tok::kw_namespace)) {
       // Inline namespaces. Allowed as an extension even in C++03.
       SourceLocation DeclEnd;
-      return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr);
+      StmtVector Stmts(Actions);
+      return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, Attr);
     }
     goto dont_know;
 
index e6e4420f23bafcfd33520582ec3d52c393a57cb4..544d9842c12439d58791765716bbe76908bd4350 100644 (file)
@@ -1691,6 +1691,25 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
   return TagD;
 }
 
+/// ActOnVlaStmt - This rouine if finds a vla expression in a decl spec.
+/// builds a statement for it and returns it so it is evaluated.
+StmtResult Sema::ActOnVlaStmt(const DeclSpec &DS) {
+  StmtResult R;
+  if (DS.getTypeSpecType() == DeclSpec::TST_typeofExpr) {
+    Expr *Exp = DS.getRepAsExpr();
+    QualType Ty = Exp->getType();
+    if (Ty->isPointerType()) {
+      do
+        Ty = Ty->getAs<PointerType>()->getPointeeType();
+      while (Ty->isPointerType());
+    }
+    if (Ty->isVariableArrayType()) {
+      R = ActOnExprStmt(MakeFullExpr(Exp));
+    }
+  }
+  return R;
+}
+
 /// We are trying to inject an anonymous member into the given scope;
 /// check if there's an existing declaration that can't be overloaded.
 ///
index 06d17b88d346e9d21acf362c13983e3b244d48b9..fa7a22fd0bdfb9fc12b569b088da681bde004e39 100644 (file)
@@ -73,3 +73,15 @@ void test1() {
      function(1, bork[2]);
 }
 
+// rdar://8476159
+static int GLOB;
+int test2(int n)
+{
+  GLOB = 0;
+  char b[1][n+3];                      /* Variable length array.  */
+  // CHECK:  [[tmp_1:%.*]] = load i32* @GLOB, align 4
+  // CHECK-NEXT: add nsw i32 [[tmp_1]], 1
+  __typeof__(b[GLOB++]) c;
+  return GLOB;
+}
+