[cfe-commits] r148592 - in /cfe/trunk: include/clang/Basic/Attr.td include/clang/CMakeLists.txt include/clang/Makefile include/clang/Sema/CMakeLists.txt include/clang/Sema/Makefile lib/Sema/CMakeLists.txt lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/warn-thread-safety-analysis.cpp utils/TableGen/ClangAttrEmitter.cpp utils/TableGen/ClangAttrEmitter.h utils/TableGen/TableGen.cpp
DeLesley Hutchins
delesley at google.com
Fri Jan 20 14:37:07 PST 2012
Author: delesley
Date: Fri Jan 20 16:37:06 2012
New Revision: 148592
URL: http://llvm.org/viewvc/llvm-project?rev=148592&view=rev
Log:
Instantiate dependent attributes when instantiating templates.
Added:
cfe/trunk/include/clang/Sema/CMakeLists.txt
cfe/trunk/include/clang/Sema/Makefile
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/CMakeLists.txt
cfe/trunk/include/clang/Makefile
cfe/trunk/lib/Sema/CMakeLists.txt
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp
cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
cfe/trunk/utils/TableGen/ClangAttrEmitter.h
cfe/trunk/utils/TableGen/TableGen.cpp
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Fri Jan 20 16:37:06 2012
@@ -93,6 +93,8 @@
list<string> Namespaces = [];
// Set to true for attributes with arguments which require delayed parsing.
bit LateParsed = 0;
+ // Set to true for attributes which must be instantiated within templates
+ bit TemplateDependent = 0;
// Any additional text that should be included verbatim in the class.
code AdditionalMembers = [{}];
}
@@ -601,36 +603,42 @@
let Spellings = ["guarded_by"];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
def PtGuardedBy : InheritableAttr {
let Spellings = ["pt_guarded_by"];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
def AcquiredAfter : InheritableAttr {
let Spellings = ["acquired_after"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
def AcquiredBefore : InheritableAttr {
let Spellings = ["acquired_before"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
def ExclusiveLockFunction : InheritableAttr {
let Spellings = ["exclusive_lock_function"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
def SharedLockFunction : InheritableAttr {
let Spellings = ["shared_lock_function"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
// The first argument is an integer or boolean value specifying the return value
@@ -639,6 +647,7 @@
let Spellings = ["exclusive_trylock_function"];
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
// The first argument is an integer or boolean value specifying the return value
@@ -647,34 +656,40 @@
let Spellings = ["shared_trylock_function"];
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
def UnlockFunction : InheritableAttr {
let Spellings = ["unlock_function"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
def LockReturned : InheritableAttr {
let Spellings = ["lock_returned"];
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
def LocksExcluded : InheritableAttr {
let Spellings = ["locks_excluded"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
def ExclusiveLocksRequired : InheritableAttr {
let Spellings = ["exclusive_locks_required"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
def SharedLocksRequired : InheritableAttr {
let Spellings = ["shared_locks_required"];
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
+ let TemplateDependent = 1;
}
Modified: cfe/trunk/include/clang/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CMakeLists.txt?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/include/clang/CMakeLists.txt (original)
+++ cfe/trunk/include/clang/CMakeLists.txt Fri Jan 20 16:37:06 2012
@@ -3,4 +3,5 @@
add_subdirectory(Driver)
add_subdirectory(Lex)
add_subdirectory(Parse)
+add_subdirectory(Sema)
add_subdirectory(Serialization)
Modified: cfe/trunk/include/clang/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Makefile?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/include/clang/Makefile (original)
+++ cfe/trunk/include/clang/Makefile Fri Jan 20 16:37:06 2012
@@ -1,5 +1,5 @@
CLANG_LEVEL := ../..
-DIRS := AST Basic Driver Lex Parse Serialization
+DIRS := AST Basic Driver Lex Parse Sema Serialization
include $(CLANG_LEVEL)/Makefile
Added: cfe/trunk/include/clang/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CMakeLists.txt?rev=148592&view=auto
==============================================================================
--- cfe/trunk/include/clang/Sema/CMakeLists.txt (added)
+++ cfe/trunk/include/clang/Sema/CMakeLists.txt Fri Jan 20 16:37:06 2012
@@ -0,0 +1,4 @@
+clang_tablegen(AttrTemplateInstantiate.inc -gen-clang-attr-template-instantiate
+ -I ${CMAKE_CURRENT_SOURCE_DIR}/../../
+ SOURCE ../Basic/Attr.td
+ TARGET ClangAttrTemplateInstantiate)
Added: cfe/trunk/include/clang/Sema/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Makefile?rev=148592&view=auto
==============================================================================
--- cfe/trunk/include/clang/Sema/Makefile (added)
+++ cfe/trunk/include/clang/Sema/Makefile Fri Jan 20 16:37:06 2012
@@ -0,0 +1,14 @@
+CLANG_LEVEL := ../../..
+TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
+BUILT_SOURCES = AttrTemplateInstantiate.inc
+
+TABLEGEN_INC_FILES_COMMON = 1
+
+include $(CLANG_LEVEL)/Makefile
+
+$(ObjDir)/AttrTemplateInstantiate.inc.tmp : $(TD_SRC_DIR)/Attr.td \
+ $(CLANG_TBLGEN) $(ObjDir)/.dir
+ $(Echo) "Building Clang attribute template instantiate code with tablegen"
+ $(Verb) $(ClangTableGen) -gen-clang-attr-template-instantiate -o \
+ $(call SYSPATH, $@) -I $(PROJ_SRC_DIR)/../../ $<
+
Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Fri Jan 20 16:37:06 2012
@@ -44,4 +44,5 @@
)
add_dependencies(clangSema ClangARMNeon ClangAttrClasses ClangAttrList
- ClangDiagnosticSema ClangDeclNodes ClangStmtNodes)
+ ClangDiagnosticSema ClangDeclNodes ClangStmtNodes
+ ClangAttrTemplateInstantiate)
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jan 20 16:37:06 2012
@@ -7311,6 +7311,9 @@
/// relevant Decl.
void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
ParsedAttributes &Attrs) {
+ // Always attach attributes to the underlying decl.
+ if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+ D = TD->getTemplatedDecl();
ProcessDeclAttributeList(S, D, Attrs.getList());
}
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Jan 20 16:37:06 2012
@@ -393,13 +393,11 @@
if (pointer && !checkIsPointer(S, D, Attr))
return;
- if (Arg->isTypeDependent())
- // FIXME: handle attributes with dependent types
- return;
-
- // check that the argument is lockable object
- if (!checkForLockableRecord(S, D, Attr, getRecordType(Arg->getType())))
- return;
+ if (!Arg->isTypeDependent()) {
+ if (!checkForLockableRecord(S, D, Attr, getRecordType(Arg->getType())))
+ return;
+ // FIXME -- semantic checks for dependent attributes
+ }
if (pointer)
D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(),
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Jan 20 16:37:06 2012
@@ -57,7 +57,9 @@
return false;
}
-// FIXME: Is this still too simple?
+// Include attribute instantiation code.
+#include "clang/Sema/AttrTemplateInstantiate.inc"
+
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Decl *Tmpl, Decl *New) {
for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
@@ -87,8 +89,8 @@
}
}
- // FIXME: Is cloning correct for all attributes?
- Attr *NewAttr = TmplAttr->clone(Context);
+ Attr *NewAttr =
+ instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs);
New->addAttr(NewAttr);
}
}
Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Fri Jan 20 16:37:06 2012
@@ -1051,12 +1051,14 @@
public:
void func(T x) {
mu_.Lock();
- count_ = x;
+ // count_ = x;
mu_.Unlock();
}
private:
- T count_ GUARDED_BY(mu_);
+ // FIXME: This test passed earlier only because thread safety was turned
+ // off for templates.
+ // T count_ GUARDED_BY(mu_);
Bar<T> bar_;
Mutex mu_;
};
@@ -1605,7 +1607,6 @@
} // end namespace test_scoped_lockable
-
namespace FunctionAttrTest {
class Foo {
@@ -1727,4 +1728,127 @@
}; // end TestTrylock
+namespace TestTemplateAttributeInstantiation {
+
+class Foo1 {
+public:
+ Mutex mu_;
+ int a GUARDED_BY(mu_);
+};
+
+class Foo2 {
+public:
+ int a GUARDED_BY(mu_);
+ Mutex mu_;
+};
+
+
+class Bar {
+public:
+ // Test non-dependent expressions in attributes on template functions
+ template <class T>
+ void barND(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(foo->mu_) {
+ foo->a = 0;
+ }
+
+ // Test dependent expressions in attributes on template functions
+ template <class T>
+ void barD(Foo1 *foo, T *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooT->mu_) {
+ fooT->a = 0;
+ }
+};
+
+
+template <class T>
+class BarT {
+public:
+ Foo1 fooBase;
+ T fooBaseT;
+
+ // Test non-dependent expression in ordinary method on template class
+ void barND() EXCLUSIVE_LOCKS_REQUIRED(fooBase.mu_) {
+ fooBase.a = 0;
+ }
+
+ // Test dependent expressions in ordinary methods on template class
+ void barD() EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_) {
+ fooBaseT.a = 0;
+ }
+
+ // Test dependent expressions in template method in template class
+ template <class T2>
+ void barTD(T2 *fooT) EXCLUSIVE_LOCKS_REQUIRED(fooBaseT.mu_, fooT->mu_) {
+ fooBaseT.a = 0;
+ fooT->a = 0;
+ }
+};
+
+template <class T>
+class Cell {
+public:
+ Mutex mu_;
+ // Test dependent guarded_by
+ T data GUARDED_BY(mu_);
+
+ void foo() {
+ mu_.Lock();
+ data = 0;
+ mu_.Unlock();
+ }
+};
+
+
+template <class T>
+class CellDelayed {
+public:
+ // Test dependent guarded_by
+ T data GUARDED_BY(mu_);
+
+ void foo() {
+ mu_.Lock();
+ data = 0;
+ mu_.Unlock();
+ }
+
+ Mutex mu_;
+};
+
+void test() {
+ Bar b;
+ BarT<Foo2> bt;
+ Foo1 f1;
+ Foo2 f2;
+
+ f1.mu_.Lock();
+ f2.mu_.Lock();
+ bt.fooBase.mu_.Lock();
+ bt.fooBaseT.mu_.Lock();
+
+ b.barND(&f1, &f2);
+ b.barD(&f1, &f2);
+ bt.barND();
+ bt.barD();
+ bt.barTD(&f2);
+
+ f1.mu_.Unlock();
+ bt.barTD(&f1); // \
+ // expected-warning {{calling function 'barTD' requires exclusive lock on 'mu_'}}
+
+ bt.fooBase.mu_.Unlock();
+ bt.fooBaseT.mu_.Unlock();
+ f2.mu_.Unlock();
+
+ Cell<int> cell;
+ cell.data = 0; // \
+ // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
+ cell.foo();
+
+ // FIXME: This doesn't work yet
+ // CellDelayed<int> celld;
+ // celld.foo();
+}
+
+}; // end namespace TestTemplateAttributeInstantiation
+
+
Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Fri Jan 20 16:37:06 2012
@@ -89,6 +89,8 @@
virtual void writeAccessors(raw_ostream &OS) const = 0;
virtual void writeAccessorDefinitions(raw_ostream &OS) const {}
virtual void writeCloneArgs(raw_ostream &OS) const = 0;
+ virtual void writeTemplateInstantiationArgs(raw_ostream &OS) const = 0;
+ virtual void writeTemplateInstantiation(raw_ostream &OS) const {};
virtual void writeCtorBody(raw_ostream &OS) const {}
virtual void writeCtorInitializers(raw_ostream &OS) const = 0;
virtual void writeCtorParameters(raw_ostream &OS) const = 0;
@@ -107,6 +109,8 @@
: Argument(Arg, Attr), type(T)
{}
+ std::string getType() const { return type; }
+
void writeAccessors(raw_ostream &OS) const {
OS << " " << type << " get" << getUpperName() << "() const {\n";
OS << " return " << getLowerName() << ";\n";
@@ -115,6 +119,9 @@
void writeCloneArgs(raw_ostream &OS) const {
OS << getLowerName();
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "A->get" << getUpperName() << "()";
+ }
void writeCtorInitializers(raw_ostream &OS) const {
OS << getLowerName() << "(" << getUpperName() << ")";
}
@@ -176,6 +183,9 @@
void writeCloneArgs(raw_ostream &OS) const {
OS << "get" << getUpperName() << "()";
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "A->get" << getUpperName() << "()";
+ }
void writeCtorBody(raw_ostream &OS) const {
OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
<< ".data(), " << getLowerName() << "Length);";
@@ -266,6 +276,10 @@
<< "Expr) : " << getLowerName()
<< "Type";
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ // FIXME: move the definition in Sema::InstantiateAttrs to here.
+ // In the meantime, aligned attributes are cloned.
+ }
void writeCtorBody(raw_ostream &OS) const {
OS << " if (is" << getLowerName() << "Expr)\n";
OS << " " << getLowerName() << "Expr = reinterpret_cast<Expr *>("
@@ -341,6 +355,11 @@
void writeCloneArgs(raw_ostream &OS) const {
OS << getLowerName() << ", " << getLowerName() << "Size";
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ // This isn't elegant, but we have to go through public methods...
+ OS << "A->" << getLowerName() << "_begin(), "
+ << "A->" << getLowerName() << "_size()";
+ }
void writeCtorBody(raw_ostream &OS) const {
// FIXME: memcpy is not safe on non-trivial types.
OS << " std::memcpy(" << getLowerName() << ", " << getUpperName()
@@ -412,6 +431,9 @@
void writeCloneArgs(raw_ostream &OS) const {
OS << getLowerName();
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "A->get" << getUpperName() << "()";
+ }
void writeCtorInitializers(raw_ostream &OS) const {
OS << getLowerName() << "(" << getUpperName() << ")";
}
@@ -475,6 +497,9 @@
void writeCloneArgs(raw_ostream &OS) const {
OS << "get" << getUpperName() << "()";
}
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "A->get" << getUpperName() << "()";
+ }
void writeCtorBody(raw_ostream &OS) const {
}
void writeCtorInitializers(raw_ostream &OS) const {
@@ -500,6 +525,61 @@
OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
}
};
+
+ class ExprArgument : public SimpleArgument {
+ public:
+ ExprArgument(Record &Arg, StringRef Attr)
+ : SimpleArgument(Arg, Attr, "Expr *")
+ {}
+
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "tempInst" << getUpperName();
+ }
+
+ void writeTemplateInstantiation(raw_ostream &OS) const {
+ OS << " " << getType() << " tempInst" << getUpperName() << ";\n";
+ OS << " {\n";
+ OS << " EnterExpressionEvaluationContext "
+ << "Unevaluated(S, Sema::Unevaluated);\n";
+ OS << " ExprResult " << "Result = S.SubstExpr("
+ << "A->get" << getUpperName() << "(), TemplateArgs);\n";
+ OS << " tempInst" << getUpperName() << " = "
+ << "Result.takeAs<Expr>();\n";
+ OS << " }\n";
+ }
+ };
+
+ class VariadicExprArgument : public VariadicArgument {
+ public:
+ VariadicExprArgument(Record &Arg, StringRef Attr)
+ : VariadicArgument(Arg, Attr, "Expr *")
+ {}
+
+ void writeTemplateInstantiationArgs(raw_ostream &OS) const {
+ OS << "tempInst" << getUpperName() << ", "
+ << "A->" << getLowerName() << "_size()";
+ }
+
+ void writeTemplateInstantiation(raw_ostream &OS) const {
+ OS << " " << getType() << " *tempInst" << getUpperName()
+ << " = new (C, 16) " << getType()
+ << "[A->" << getLowerName() << "_size()];\n";
+ OS << " {\n";
+ OS << " EnterExpressionEvaluationContext "
+ << "Unevaluated(S, Sema::Unevaluated);\n";
+ OS << " " << getType() << " *TI = tempInst" << getUpperName()
+ << ";\n";
+ OS << " " << getType() << " *I = A->" << getLowerName()
+ << "_begin();\n";
+ OS << " " << getType() << " *E = A->" << getLowerName()
+ << "_end();\n";
+ OS << " for (; I != E; ++I, ++TI) {\n";
+ OS << " ExprResult Result = S.SubstExpr(*I, TemplateArgs);\n";
+ OS << " *TI = Result.takeAs<Expr>();\n";
+ OS << " }\n";
+ OS << " }\n";
+ }
+ };
}
static Argument *createArgument(Record &Arg, StringRef Attr,
@@ -512,8 +592,7 @@
if (ArgName == "AlignedArgument") Ptr = new AlignedArgument(Arg, Attr);
else if (ArgName == "EnumArgument") Ptr = new EnumArgument(Arg, Attr);
- else if (ArgName == "ExprArgument") Ptr = new SimpleArgument(Arg, Attr,
- "Expr *");
+ else if (ArgName == "ExprArgument") Ptr = new ExprArgument(Arg, Attr);
else if (ArgName == "FunctionArgument")
Ptr = new SimpleArgument(Arg, Attr, "FunctionDecl *");
else if (ArgName == "IdentifierArgument")
@@ -531,7 +610,7 @@
else if (ArgName == "VariadicUnsignedArgument")
Ptr = new VariadicArgument(Arg, Attr, "unsigned");
else if (ArgName == "VariadicExprArgument")
- Ptr = new VariadicArgument(Arg, Attr, "Expr *");
+ Ptr = new VariadicExprArgument(Arg, Attr);
else if (ArgName == "VersionArgument")
Ptr = new VersionArgument(Arg, Attr);
@@ -851,3 +930,63 @@
}
}
}
+
+
+void ClangAttrTemplateInstantiateEmitter::run(raw_ostream &OS) {
+ OS << "// This file is generated by TableGen. Do not edit.\n\n";
+
+ std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
+
+ OS << "Attr* instantiateTemplateAttribute(const Attr *At, ASTContext &C, "
+ << "Sema &S,\n"
+ << " const MultiLevelTemplateArgumentList &TemplateArgs) {\n"
+ << " switch (At->getKind()) {\n"
+ << " default:\n"
+ << " break;\n";
+
+ for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+ I != E; ++I) {
+ Record &R = **I;
+
+ OS << " case attr::" << R.getName() << ": {\n";
+ OS << " const " << R.getName() << "Attr *A = cast<"
+ << R.getName() << "Attr>(At);\n";
+ bool TDependent = R.getValueAsBit("TemplateDependent");
+
+ if (!TDependent) {
+ OS << " return A->clone(C);\n";
+ OS << " }\n";
+ continue;
+ }
+
+ std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
+ std::vector<Argument*> Args;
+ std::vector<Argument*>::iterator ai, ae;
+ Args.reserve(ArgRecords.size());
+
+ for (std::vector<Record*>::iterator ri = ArgRecords.begin(),
+ re = ArgRecords.end();
+ ri != re; ++ri) {
+ Record &ArgRecord = **ri;
+ Argument *Arg = createArgument(ArgRecord, R.getName());
+ assert(Arg);
+ Args.push_back(Arg);
+ }
+ ae = Args.end();
+
+ for (ai = Args.begin(); ai != ae; ++ai) {
+ (*ai)->writeTemplateInstantiation(OS);
+ }
+ OS << " return new (C) " << R.getName() << "Attr(A->getLocation(), C";
+ for (ai = Args.begin(); ai != ae; ++ai) {
+ OS << ", ";
+ (*ai)->writeTemplateInstantiationArgs(OS);
+ }
+ OS << ");\n }\n";
+ }
+ OS << " } // end switch\n"
+ << " llvm_unreachable(\"Unknown attribute!\");\n"
+ << " return 0;\n"
+ << "}\n\n";
+}
+
Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.h?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.h (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.h Fri Jan 20 16:37:06 2012
@@ -109,6 +109,19 @@
void run(raw_ostream &OS);
};
+/// ClangAttrTemplateInstantiateEmitter emits code to instantiate dependent
+/// attributes on templates.
+class ClangAttrTemplateInstantiateEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+
+ public:
+ explicit ClangAttrTemplateInstantiateEmitter(RecordKeeper &R)
+ : Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+};
+
}
#endif
Modified: cfe/trunk/utils/TableGen/TableGen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/TableGen.cpp?rev=148592&r1=148591&r2=148592&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/TableGen.cpp (original)
+++ cfe/trunk/utils/TableGen/TableGen.cpp Fri Jan 20 16:37:06 2012
@@ -36,6 +36,7 @@
GenClangAttrPCHWrite,
GenClangAttrSpellingList,
GenClangAttrLateParsedList,
+ GenClangAttrTemplateInstantiate,
GenClangDiagsDefs,
GenClangDiagGroups,
GenClangDiagsIndexName,
@@ -71,6 +72,9 @@
clEnumValN(GenClangAttrLateParsedList,
"gen-clang-attr-late-parsed-list",
"Generate a clang attribute LateParsed list"),
+ clEnumValN(GenClangAttrTemplateInstantiate,
+ "gen-clang-attr-template-instantiate",
+ "Generate a clang template instantiate code"),
clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
"Generate Clang diagnostics definitions"),
clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
@@ -122,6 +126,9 @@
case GenClangAttrLateParsedList:
ClangAttrLateParsedListEmitter(Records).run(OS);
break;
+ case GenClangAttrTemplateInstantiate:
+ ClangAttrTemplateInstantiateEmitter(Records).run(OS);
+ break;
case GenClangDiagsDefs:
ClangDiagsDefsEmitter(Records, ClangComponent).run(OS);
break;
More information about the cfe-commits
mailing list