summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Parse/CMakeLists.txt5
-rw-r--r--clang/include/clang/Parse/Makefile8
-rw-r--r--clang/lib/Parse/CMakeLists.txt1
-rw-r--r--clang/lib/Parse/ParseDecl.cpp10
-rw-r--r--clang/lib/Sema/SemaDecl.cpp4
-rw-r--r--clang/test/SemaObjC/format-arg-attribute.m2
-rw-r--r--clang/test/SemaTemplate/attributes.cpp22
-rw-r--r--clang/utils/TableGen/ClangAttrEmitter.cpp42
-rw-r--r--clang/utils/TableGen/TableGen.cpp8
-rw-r--r--clang/utils/TableGen/TableGenBackends.h1
10 files changed, 98 insertions, 5 deletions
diff --git a/clang/include/clang/Parse/CMakeLists.txt b/clang/include/clang/Parse/CMakeLists.txt
index d1ff2abfee6..d20708e58c5 100644
--- a/clang/include/clang/Parse/CMakeLists.txt
+++ b/clang/include/clang/Parse/CMakeLists.txt
@@ -1,3 +1,8 @@
+clang_tablegen(AttrExprArgs.inc -gen-clang-attr-expr-args-list
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+ SOURCE ../Basic/Attr.td
+ TARGET ClangAttrExprArgs)
+
clang_tablegen(AttrLateParsed.inc -gen-clang-attr-late-parsed-list
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
diff --git a/clang/include/clang/Parse/Makefile b/clang/include/clang/Parse/Makefile
index 296892c5b6e..fb63175ba9b 100644
--- a/clang/include/clang/Parse/Makefile
+++ b/clang/include/clang/Parse/Makefile
@@ -1,11 +1,17 @@
CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
-BUILT_SOURCES = AttrLateParsed.inc
+BUILT_SOURCES = AttrExprArgs.inc AttrLateParsed.inc
TABLEGEN_INC_FILES_COMMON = 1
include $(CLANG_LEVEL)/Makefile
+$(ObjDir)/AttrExprArgs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
+ $(ObjDir)/.dir
+ $(Echo) "Building Clang attribute expression arguments table with tblgen"
+ $(Verb) $(ClangTableGen) -gen-clang-attr-expr-args-list -o $(call SYSPATH, $@) \
+ -I $(PROJ_SRC_DIR)/../../ $<
+
$(ObjDir)/AttrLateParsed.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang attribute late-parsed table with tblgen"
diff --git a/clang/lib/Parse/CMakeLists.txt b/clang/lib/Parse/CMakeLists.txt
index 939998ecb1a..01c0694d035 100644
--- a/clang/lib/Parse/CMakeLists.txt
+++ b/clang/lib/Parse/CMakeLists.txt
@@ -17,6 +17,7 @@ add_clang_library(clangParse
add_dependencies(clangParse
ClangAttrClasses
+ ClangAttrExprArgs
ClangAttrLateParsed
ClangAttrList
ClangAttrParsedAttrList
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 2f0c1a3b8da..a4cec8c2575 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -178,6 +178,12 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
}
}
+/// \brief Determine whether the given attribute has all expression arguments.
+static bool attributeHasExprArgs(const IdentifierInfo &II) {
+ return llvm::StringSwitch<bool>(II.getName())
+#include "clang/Parse/AttrExprArgs.inc"
+ .Default(false);
+}
/// Parse the arguments to a parameterized GNU attribute or
/// a C++11 attribute in "gnu" namespace.
@@ -247,6 +253,10 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
TypeParsed = true;
break;
}
+ // If the attribute has all expression arguments, and not a "parameter",
+ // break out to handle it below.
+ if (attributeHasExprArgs(*AttrName))
+ break;
ParmName = Tok.getIdentifierInfo();
ParmLoc = ConsumeToken();
break;
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1aab5c669f9..cc8cb4a3951 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10633,8 +10633,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T,
// FIXME: We need to pass in the attributes given an AST
// representation, not a parser representation.
if (D) {
- // FIXME: What to pass instead of TUScope?
- ProcessDeclAttributes(TUScope, NewFD, *D);
+ // FIXME: The current scope is almost... but not entirely... correct here.
+ ProcessDeclAttributes(getCurScope(), NewFD, *D);
if (NewFD->hasAttrs())
CheckAlignasUnderalignment(NewFD);
diff --git a/clang/test/SemaObjC/format-arg-attribute.m b/clang/test/SemaObjC/format-arg-attribute.m
index 6edb8fd99b3..dede433f37a 100644
--- a/clang/test/SemaObjC/format-arg-attribute.m
+++ b/clang/test/SemaObjC/format-arg-attribute.m
@@ -14,7 +14,7 @@ union u1 { int i; } __attribute__((format_arg(1))); // expected-warning {{'form
enum e1 { E1V0 } __attribute__((format_arg(1))); // expected-warning {{'format_arg' attribute only applies to functions}}
extern NSString *ff3 (const NSString *) __attribute__((format_arg(3-2)));
-extern NSString *ff4 (const NSString *) __attribute__((format_arg(foo))); // expected-error {{attribute takes one argument}}
+extern NSString *ff4 (const NSString *) __attribute__((format_arg(foo))); // expected-error {{use of undeclared identifier 'foo'}}
/* format_arg formats must take and return a string. */
extern NSString *fi0 (int) __attribute__((format_arg(1))); // expected-error {{format argument not a string type}}
diff --git a/clang/test/SemaTemplate/attributes.cpp b/clang/test/SemaTemplate/attributes.cpp
index 495f4a7ad38..5a06a706aa8 100644
--- a/clang/test/SemaTemplate/attributes.cpp
+++ b/clang/test/SemaTemplate/attributes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -verify %s
namespace attribute_aligned {
template<int N>
@@ -18,6 +18,26 @@ namespace attribute_aligned {
check_alignment<2>::t c2;
check_alignment<3>::t c3; // expected-note 2 {{in instantiation}}
check_alignment<4>::t c4;
+
+ template<unsigned Size, unsigned Align>
+ class my_aligned_storage
+ {
+ __attribute__((align(Align))) char storage[Size];
+ };
+
+ template<typename T>
+ class C {
+ public:
+ C() {
+ static_assert(sizeof(t) == sizeof(T), "my_aligned_storage size wrong");
+ static_assert(alignof(t) == alignof(T), "my_aligned_storage align wrong"); // expected-warning{{'alignof' applied to an expression is a GNU extension}}
+ }
+
+ private:
+ my_aligned_storage<sizeof(T), alignof(T)> t;
+ };
+
+ C<double> cd;
}
namespace PR9049 {
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 7c8603fc6c3..eb614f0f1ca 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -971,6 +971,48 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
OS << "#endif\n";
}
+// Emits the LateParsed property for attributes.
+void EmitClangAttrExprArgsList(RecordKeeper &Records, raw_ostream &OS) {
+ emitSourceFileHeader("llvm::StringSwitch code to match attributes with "
+ "expression arguments", OS);
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+
+ for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+ I != E; ++I) {
+ Record &Attr = **I;
+
+ // Determine whether the first argument is something that is always
+ // an expression.
+ std::vector<Record *> Args = Attr.getValueAsListOfDefs("Args");
+ if (Args.empty() || Args[0]->getSuperClasses().empty())
+ continue;
+
+ // Check whether this is one of the argument kinds that implies an
+ // expression.
+ // FIXME: Aligned is weird.
+ if (!llvm::StringSwitch<bool>(Args[0]->getSuperClasses().back()->getName())
+ .Case("AlignedArgument", true)
+ .Case("BoolArgument", true)
+ .Case("DefaultIntArgument", true)
+ .Case("IntArgument", true)
+ .Case("ExprArgument", true)
+ .Case("UnsignedArgument", true)
+ .Case("VariadicUnsignedArgument", true)
+ .Case("VariadicExprArgument", true)
+ .Default(false))
+ continue;
+
+ std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
+
+ for (std::vector<Record*>::const_iterator I = Spellings.begin(),
+ E = Spellings.end(); I != E; ++I) {
+ OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
+ << "true" << ")\n";
+ }
+ }
+}
+
// Emits the class method definitions for attributes.
void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Attribute classes' member function definitions", OS);
diff --git a/clang/utils/TableGen/TableGen.cpp b/clang/utils/TableGen/TableGen.cpp
index 3df8940b055..12e1c47725e 100644
--- a/clang/utils/TableGen/TableGen.cpp
+++ b/clang/utils/TableGen/TableGen.cpp
@@ -24,6 +24,7 @@ using namespace clang;
enum ActionType {
GenClangAttrClasses,
+ GenClangAttrExprArgsList,
GenClangAttrImpl,
GenClangAttrList,
GenClangAttrPCHRead,
@@ -62,6 +63,10 @@ namespace {
"Generate option parser implementation"),
clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
"Generate clang attribute clases"),
+ clEnumValN(GenClangAttrExprArgsList,
+ "gen-clang-attr-expr-args-list",
+ "Generate a clang attribute expression "
+ "arguments list"),
clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl",
"Generate clang attribute implementations"),
clEnumValN(GenClangAttrList, "gen-clang-attr-list",
@@ -143,6 +148,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenClangAttrClasses:
EmitClangAttrClass(Records, OS);
break;
+ case GenClangAttrExprArgsList:
+ EmitClangAttrExprArgsList(Records, OS);
+ break;
case GenClangAttrImpl:
EmitClangAttrImpl(Records, OS);
break;
diff --git a/clang/utils/TableGen/TableGenBackends.h b/clang/utils/TableGen/TableGenBackends.h
index 03708b6a766..0ff33d775cc 100644
--- a/clang/utils/TableGen/TableGenBackends.h
+++ b/clang/utils/TableGen/TableGenBackends.h
@@ -30,6 +30,7 @@ void EmitClangASTNodes(RecordKeeper &RK, raw_ostream &OS,
const std::string &N, const std::string &S);
void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS);
+void EmitClangAttrExprArgsList(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrList(RecordKeeper &Records, raw_ostream &OS);
void EmitClangAttrPCHRead(RecordKeeper &Records, raw_ostream &OS);
OpenPOWER on IntegriCloud