]> granicus.if.org Git - clang/commitdiff
More static_assert work. Check that the assert expr is valid and show an error if...
authorAnders Carlsson <andersca@mac.com>
Sat, 14 Mar 2009 00:25:26 +0000 (00:25 +0000)
committerAnders Carlsson <andersca@mac.com>
Sat, 14 Mar 2009 00:25:26 +0000 (00:25 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66995 91177308-0d34-0410-b5e6-96231b3b80d8

clang.xcodeproj/project.pbxproj
include/clang/AST/DeclCXX.h
include/clang/AST/DeclNodes.def
include/clang/Basic/DiagnosticSemaKinds.def
include/clang/Parse/Action.h
lib/AST/DeclCXX.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/static-assert.cpp [new file with mode: 0644]

index 114aa41ec0c734434269cdd37d9b35c2b8d8fbd8..48faa12a70a20fc5b0787813560c718b5d7374a8 100644 (file)
                DEA09A040F302C65000C2258 /* DiagnosticLexKinds.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticLexKinds.def; sourceTree = "<group>"; };
                DEA09A060F302C65000C2258 /* DiagnosticParseKinds.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticParseKinds.def; sourceTree = "<group>"; };
                DEA09A080F302C65000C2258 /* DiagnosticSemaKinds.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DiagnosticSemaKinds.def; sourceTree = "<group>"; };
-               DEA09A6E0F31756F000C2258 /* ASTDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASTDiagnostic.h; path = clang/AST/ASTDiagnostic.h; sourceTree = "<group>"; };
+               DEA09A6E0F31756F000C2258 /* ASTDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = ASTDiagnostic.h; path = clang/AST/ASTDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
                DEA09A830F3175BF000C2258 /* LexDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LexDiagnostic.h; sourceTree = "<group>"; };
                DEA09A860F3175CA000C2258 /* ParseDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = ParseDiagnostic.h; path = clang/Parse/ParseDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
                DEA09A890F3175D9000C2258 /* SemaDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaDiagnostic.h; path = clang/Sema/SemaDiagnostic.h; sourceTree = "<group>"; };
                DEAABDF70F5F477C0098928A /* PrettyStackTrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrettyStackTrace.h; sourceTree = "<group>"; };
                DEAEE98A0A5A2B970045101B /* MultipleIncludeOpt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MultipleIncludeOpt.h; sourceTree = "<group>"; };
                DEAEED4A0A5AF89A0045101B /* NOTES.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = NOTES.txt; sourceTree = "<group>"; };
-               DEB076C90F3A221200F5A2BE /* DeclTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeclTemplate.h; path = clang/AST/DeclTemplate.h; sourceTree = "<group>"; };
+               DEB076C90F3A221200F5A2BE /* DeclTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = DeclTemplate.h; path = clang/AST/DeclTemplate.h; sourceTree = "<group>"; tabWidth = 2; };
                DEB076CE0F3A222200F5A2BE /* DeclTemplate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DeclTemplate.cpp; path = lib/AST/DeclTemplate.cpp; sourceTree = "<group>"; };
                DEB077930F44F96000F5A2BE /* TokenConcatenation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TokenConcatenation.h; sourceTree = "<group>"; };
                DEB077980F44F97800F5A2BE /* TokenConcatenation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TokenConcatenation.cpp; sourceTree = "<group>"; };
                DED7D7D70A524302003AD0FB /* README.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README.txt; sourceTree = "<group>"; };
                DED7D9170A52518C003AD0FB /* ScratchBuffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ScratchBuffer.h; sourceTree = "<group>"; };
                DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ScratchBuffer.cpp; sourceTree = "<group>"; };
-               DEDFE5270F63A9230035BD10 /* DeclNodes.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = DeclNodes.def; path = clang/AST/DeclNodes.def; sourceTree = "<group>"; };
+               DEDFE5270F63A9230035BD10 /* DeclNodes.def */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = text; name = DeclNodes.def; path = clang/AST/DeclNodes.def; sourceTree = "<group>"; tabWidth = 2; };
                DEEBBD430C19C5D200A9FE82 /* TODO.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = TODO.txt; sourceTree = "<group>"; };
                DEEBC3B90C2363B800A9FE82 /* CodeGenTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CodeGenTypes.h; path = lib/CodeGen/CodeGenTypes.h; sourceTree = "<group>"; tabWidth = 2; };
                DEEBC3BB0C2363BC00A9FE82 /* CodeGenTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CodeGenTypes.cpp; path = lib/CodeGen/CodeGenTypes.cpp; sourceTree = "<group>"; tabWidth = 2; };
index 7b5eba78f7c1422136bece45d75fc0a100549249..43a91b47c78c401bcb8b0c9beae26a3fcf537921 100644 (file)
@@ -886,6 +886,30 @@ public:
   friend class DeclContext;
 };
 
+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) { }
+  
+public:
+  static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC,
+                                  SourceLocation L, Expr *AssertExpr,
+                                  StringLiteral *Message);
+  
+  virtual ~StaticAssertDecl();
+  virtual void Destroy(ASTContext& C);
+
+  static bool classof(const Decl *D) {
+    return D->getKind() == Decl::StaticAssert;
+  }
+  static bool classof(StaticAssertDecl *D) { return true; }
+};
+  
 } // end namespace clang
 
 #endif
index 43bf7f1023cb257b7c3027f49eba111fe1d79ea5..d4c8c5e6ba5642fd34c4f768333856d39ebfe6d0 100644 (file)
@@ -120,6 +120,7 @@ DECL(ObjCPropertyImpl, Decl)
 DECL(ObjCForwardProtocol, Decl)
 DECL(ObjCClass, Decl)
 DECL(FileScopeAsm, Decl)
+DECL(StaticAssert, Decl)
 LAST_DECL(Block, Decl)
 
 // Declaration contexts. DECL_CONTEXT_BASE indicates that it has subclasses.
index be17a9746ddd1261c8de11e75cc57ab1bc88dc91..4d721bc33166ce698235fd52e9bcf22d6d509201 100644 (file)
@@ -231,6 +231,12 @@ DIAG(error_property_implemented, ERROR,
 DIAG(warn_objc_property_attr_mutually_exclusive, WARNING,
      "property attributes '%0' and '%1' are mutually exclusive")
 
+// C++ declarations
+DIAG(err_static_assert_expression_is_not_constant, ERROR,
+    "static_assert expression is not an integral constant expression")
+DIAG(err_static_assert_failed, ERROR,
+    "static_assert failed \"%0\"")
+    
 // C++ name lookup
 DIAG(err_incomplete_nested_name_spec, ERROR,
      "incomplete type %0 named in nested name specifier")
index 3900e38da79c08745c8d1b3f3ab00c5d72c1e991..3df0d1dd7de22e00df64dd62b7f0dcb29266dccc 100644 (file)
@@ -884,6 +884,7 @@ public:
   virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method) {
   }
 
+  /// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration.
   virtual DeclTy *ActOnStaticAssertDeclaration(SourceLocation AssertLoc, 
                                                ExprArg AssertExpr,
                                                ExprArg AssertMessageExpr,
index 4776ce587782da2fff7e6dde5da929aaf7a80848..fd900834caf468d2f57d3a2d01ce7c9cb5e799fc 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Expr.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "llvm/ADT/STLExtras.h"
 using namespace clang;
@@ -339,3 +340,19 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
                                     Used, CommonAncestor);
 }
 
+StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
+                                           SourceLocation L, Expr *AssertExpr,
+                                           StringLiteral *Message) {
+  return new (C) StaticAssertDecl(DC, L, AssertExpr, Message);
+}
+
+void StaticAssertDecl::Destroy(ASTContext& C) {
+  AssertExpr->Destroy(C);
+  Message->Destroy(C);
+  this->~StaticAssertDecl();
+  C.Deallocate((void *)this);
+}
+
+StaticAssertDecl::~StaticAssertDecl() {
+}
+
index a86aa65aff288ef1892c5580597071774f054f77..54b3d197fa00009a7fba9835eac2869af5b2eeac 100644 (file)
@@ -1554,6 +1554,11 @@ public:
   virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclTy *Param);
   virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method);
 
+  virtual DeclTy *ActOnStaticAssertDeclaration(SourceLocation AssertLoc, 
+                                               ExprArg AssertExpr,
+                                               ExprArg AssertMessageExpr,
+                                               SourceLocation RParenLoc);
+  
   bool CheckConstructorDeclarator(Declarator &D, QualType &R,
                                   FunctionDecl::StorageClass& SC);
   bool CheckConstructor(CXXConstructorDecl *Constructor);
index f5d8f6b5e12ad87e0a66c958a1764f850e595d2e..57a6c6246166340346ec013ec49cfc2f83d24425 100644 (file)
@@ -2234,3 +2234,30 @@ Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D)
   ProcessDeclAttributes(ExDecl, D);
   return ExDecl;
 }
+
+Sema::DeclTy *Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, 
+                                                 ExprArg assertexpr,
+                                                 ExprArg assertmessageexpr,
+                                                 SourceLocation RParenLoc) {
+  Expr *AssertExpr = (Expr *)assertexpr.get();
+  StringLiteral *AssertMessage = 
+    cast<StringLiteral>((Expr *)assertmessageexpr.get());
+
+  llvm::APSInt Value(32);
+  if (!AssertExpr->isIntegerConstantExpr(Value, Context)) {
+    Diag(AssertLoc, diag::err_static_assert_expression_is_not_constant) <<
+      AssertExpr->getSourceRange();
+    return 0;
+  }
+
+  Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc, 
+                                        AssertExpr, AssertMessage);
+  if (Value == 0) {
+    std::string str(AssertMessage->getStrData(), 
+                    AssertMessage->getByteLength());
+    Diag(AssertLoc, diag::err_static_assert_failed) << str;
+  }
+  
+  CurContext->addDecl(Decl);
+  return Decl;
+}
diff --git a/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp
new file mode 100644 (file)
index 0000000..a2b0b52
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: clang -fsyntax-only -verify %s -std=c++0x
+
+int f();
+
+static_assert(f(), "f"); // expected-error {{static_assert expression is not an integral constant expression}}
+static_assert(true, "true is not false");
+static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}}
+
+void g() {
+    static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}}
+}
+
+class C {
+    static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}}
+};