]> granicus.if.org Git - clang/commitdiff
Handle static_asserts when instantiating structs.
authorAnders Carlsson <andersca@mac.com>
Sun, 15 Mar 2009 18:44:04 +0000 (18:44 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 15 Mar 2009 18:44:04 +0000 (18:44 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67031 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/PrintParserCallbacks.cpp
include/clang/AST/DeclCXX.h
include/clang/Parse/Action.h
lib/Parse/ParseDeclCXX.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/SemaCXX/static-assert.cpp

index f9399e2e1e411773b131791ff7e279530b1e18aa..b123505bf8d12a8627de4d7b28303c2bc7959815 100644 (file)
@@ -724,8 +724,7 @@ namespace {
 
     virtual DeclTy *ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
                                                  ExprArg AssertExpr,
-                                                 ExprArg AssertMessageExpr,
-                                                 SourceLocation RParenLoc) {
+                                                 ExprArg AssertMessageExpr) {
       llvm::cout << __FUNCTION__ << "\n";
       return 0;
     }
index 43a91b47c78c401bcb8b0c9beae26a3fcf537921..740d37f30bccda609080fafe4941e66bd5656cbb 100644 (file)
@@ -887,20 +887,24 @@ public:
 };
 
 class StaticAssertDecl : public Decl {
-  SourceLocation AssertLoc;
-
   Expr *AssertExpr;
   StringLiteral *Message;
-  
+
   StaticAssertDecl(DeclContext *DC, SourceLocation L, 
                    Expr *assertexpr, StringLiteral *message)
-    : Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { }
+  : Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { }
   
 public:
   static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC,
                                   SourceLocation L, Expr *AssertExpr,
                                   StringLiteral *Message);
   
+  Expr *getAssertExpr() { return AssertExpr; }
+  const Expr *getAssertExpr() const { return AssertExpr; }
+  
+  StringLiteral *getMessage() { return Message; }
+  const StringLiteral *getMessage() const { return Message; }
+  
   virtual ~StaticAssertDecl();
   virtual void Destroy(ASTContext& C);
 
index f33918eae8068a2c39900277560baaccf5c41524..355eed1f9151cceffbb062b37afb7f04830db4fb 100644 (file)
@@ -893,8 +893,7 @@ public:
   /// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration.
   virtual DeclTy *ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
                                                ExprArg AssertExpr,
-                                               ExprArg AssertMessageExpr,
-                                               SourceLocation RParenLoc) {
+                                               ExprArg AssertMessageExpr) {
     return 0;
   }
 
index f534f42ccb82572ee10bd12d6f9680bc8eb134a8..ec91d71b086d162a73026d2b3ebd3416f0b6a8f5 100644 (file)
@@ -252,13 +252,12 @@ Parser::DeclTy *Parser::ParseStaticAssertDeclaration() {
   if (AssertMessage.isInvalid()) 
     return 0;
 
-  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+  MatchRHSPunctuation(tok::r_paren, LParenLoc);
   
   ExpectAndConsume(tok::semi, diag::err_expected_semi_after_static_assert);
 
   return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, move(AssertExpr), 
-                                              move(AssertMessage), 
-                                              RParenLoc);
+                                              move(AssertMessage));
 }
 
 /// ParseClassName - Parse a C++ class-name, which names a class. Note
index a357ae762150d59f3b9dc5aae5c2ceb10fee1434..29d0796dcb0c75f3eb80d4e90bacffcec22ac85c 100644 (file)
@@ -1562,8 +1562,7 @@ public:
 
   virtual DeclTy *ActOnStaticAssertDeclaration(SourceLocation AssertLoc, 
                                                ExprArg AssertExpr,
-                                               ExprArg AssertMessageExpr,
-                                               SourceLocation RParenLoc);
+                                               ExprArg AssertMessageExpr);
   
   bool CheckConstructorDeclarator(Declarator &D, QualType &R,
                                   FunctionDecl::StorageClass& SC);
index 177eee2a53404eb32614caefab646a51be39870d..fa84c7d2de225921f2309feb1b85dc4f70769a0a 100644 (file)
@@ -2238,8 +2238,7 @@ Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D)
 
 Sema::DeclTy *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, 
                                                  ExprArg assertexpr,
-                                                 ExprArg assertmessageexpr,
-                                                 SourceLocation RParenLoc) {
+                                                 ExprArg assertmessageexpr) {
   Expr *AssertExpr = (Expr *)assertexpr.get();
   StringLiteral *AssertMessage = 
     cast<StringLiteral>((Expr *)assertmessageexpr.get());
@@ -2255,7 +2254,8 @@ Sema::DeclTy *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
     if (Value == 0) {
       std::string str(AssertMessage->getStrData(), 
                       AssertMessage->getByteLength());
-      Diag(AssertLoc, diag::err_static_assert_failed) << str;
+      Diag(AssertLoc, diag::err_static_assert_failed) 
+        << str << AssertExpr->getSourceRange();
     }
   }
   
index 7b2d24b5bf1d5275c6804f5961409287ed2a48df..b7f0bbc923ae7465114f866d0373cff038e6275c 100644 (file)
@@ -1071,6 +1071,25 @@ Sema::InstantiateClassTemplateSpecialization(
         if (New->isInvalidDecl())
           Invalid = true;
       }
+    } else if (StaticAssertDecl *SA = dyn_cast<StaticAssertDecl>(*Member)) {
+      Expr *AssertExpr = SA->getAssertExpr();
+      
+      OwningExprResult InstantiatedAssertExpr
+        = InstantiateExpr(AssertExpr, 
+                          ClassTemplateSpec->getTemplateArgs(),
+                          ClassTemplateSpec->getNumTemplateArgs());
+      if (!InstantiatedAssertExpr.isInvalid()) {
+        OwningExprResult Message = Clone(SA->getMessage());
+
+        Decl *New = 
+          (Decl *)ActOnStaticAssertDeclaration(SA->getLocation(), 
+                                               move(InstantiatedAssertExpr),
+                                               move(Message));
+        if (New->isInvalidDecl())
+          Invalid = true;
+          
+      } else
+        Invalid = true;
     }
   }
 
index 94ffff86cd29c4e1c6582383ca38639640a3bb51..7e1ee467adf6bb6b5e7b0cd45bf41a3e9cccac13 100644 (file)
@@ -15,10 +15,16 @@ class C {
 };
 
 template<int N> struct T {
-    static_assert(N == 2, "N is not 2!");
+    static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed "N is not 2!"}}
 };
 
+T<1> t1; // expected-note {{in instantiation of template class 'struct T<1>' requested here}}
+T<2> t2;
+
 template<typename T> struct S {
-    static_assert(sizeof(T) > sizeof(char), "Type not big enough!");
+    static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed "Type not big enough!"}}
 };
 
+S<char> s1; // expected-note {{in instantiation of template class 'struct S<char>' requested here}}
+S<int> s2;
+