r199676 - Remove some hard-coded specialness for thread-safety attributes from the parser, and made it more declarative. If an attribute is allowed to appear on a function definition when late parsed, it can now use the FunctionDefinition attribute subject. It's treated as a FunctionDecl for most purposes, except it also gets exposed on the AttributeList so that it can be used while parsing.
Aaron Ballman
aaron at aaronballman.com
Mon Jan 20 09:18:36 PST 2014
Author: aaronballman
Date: Mon Jan 20 11:18:35 2014
New Revision: 199676
URL: http://llvm.org/viewvc/llvm-project?rev=199676&view=rev
Log:
Remove some hard-coded specialness for thread-safety attributes from the parser, and made it more declarative. If an attribute is allowed to appear on a function definition when late parsed, it can now use the FunctionDefinition attribute subject. It's treated as a FunctionDecl for most purposes, except it also gets exposed on the AttributeList so that it can be used while parsing.
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/AttributeList.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/AttributeList.cpp
cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=199676&r1=199675&r2=199676&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Mon Jan 20 11:18:35 2014
@@ -74,6 +74,12 @@ def HasFunctionProto : SubsetSubject<Dec
isa<ObjCMethodDecl>(S) ||
isa<BlockDecl>(S)}]>;
+// This is a fake Decl node that represents a function definition as well as a
+// function declaration. This can be used for attributes which are allowed to
+// appear on the definition of a function that's been late parsed. It is
+// treated and diagnosed the same as a FunctionDecl.
+def FunctionDefinition : DDecl<Function, 1>;
+
// A single argument to an attribute
class Argument<string name, bit optional> {
string Name = name;
@@ -1097,7 +1103,7 @@ def ScopedLockable : InheritableAttr {
def NoThreadSafetyAnalysis : InheritableAttr {
let Spellings = [GNU<"no_thread_safety_analysis">];
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def GuardedBy : InheritableAttr {
@@ -1146,7 +1152,7 @@ def ExclusiveLockFunction : InheritableA
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def SharedLockFunction : InheritableAttr {
@@ -1155,7 +1161,7 @@ def SharedLockFunction : InheritableAttr
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def AssertExclusiveLock : InheritableAttr {
@@ -1164,7 +1170,7 @@ def AssertExclusiveLock : InheritableAtt
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def AssertSharedLock : InheritableAttr {
@@ -1173,7 +1179,7 @@ def AssertSharedLock : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
// The first argument is an integer or boolean value specifying the return value
@@ -1184,7 +1190,7 @@ def ExclusiveTrylockFunction : Inheritab
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
// The first argument is an integer or boolean value specifying the return value
@@ -1195,7 +1201,7 @@ def SharedTrylockFunction : InheritableA
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def UnlockFunction : InheritableAttr {
@@ -1204,7 +1210,7 @@ def UnlockFunction : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def LockReturned : InheritableAttr {
@@ -1213,7 +1219,7 @@ def LockReturned : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def LocksExcluded : InheritableAttr {
@@ -1222,7 +1228,7 @@ def LocksExcluded : InheritableAttr {
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def ExclusiveLocksRequired : InheritableAttr {
@@ -1231,7 +1237,7 @@ def ExclusiveLocksRequired : Inheritable
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
def SharedLocksRequired : InheritableAttr {
@@ -1240,7 +1246,7 @@ def SharedLocksRequired : InheritableAtt
let LateParsed = 1;
let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1;
- let Subjects = SubjectList<[Function, FunctionTemplate]>;
+ let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
}
// C/C++ consumed attributes.
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=199676&r1=199675&r2=199676&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Jan 20 11:18:35 2014
@@ -2066,8 +2066,6 @@ private:
ParsedAttributes &attrs,
SourceLocation *endLoc);
- bool IsThreadSafetyAttribute(StringRef AttrName);
-
void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=199676&r1=199675&r2=199676&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Mon Jan 20 11:18:35 2014
@@ -494,6 +494,7 @@ public:
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
bool diagnoseLangOpts(class Sema &S) const;
bool existsInTarget(llvm::Triple T) const;
+ bool canAppearOnFunctionDefinition() const;
};
/// A factory, from which one makes pools, from which one creates
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=199676&r1=199675&r2=199676&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Jan 20 11:18:35 2014
@@ -1096,13 +1096,6 @@ void Parser::ParseLexedAttribute(LatePar
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
- if (OnDefinition && !IsThreadSafetyAttribute(LA.AttrName.getName())) {
- // FIXME: Do not warn on C++11 attributes, once we start supporting
- // them here.
- Diag(Tok, diag::warn_attribute_on_function_definition)
- << &LA.AttrName;
- }
-
ParsedAttributes Attrs(AttrFactory);
SourceLocation endLoc;
@@ -1148,9 +1141,14 @@ void Parser::ParseLexedAttribute(LatePar
Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();
}
- for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i) {
+ const AttributeList *AL = Attrs.getList();
+ if (OnDefinition && AL && !AL->isCXX11Attribute() &&
+ !AL->canAppearOnFunctionDefinition())
+ Diag(Tok, diag::warn_attribute_on_function_definition)
+ << &LA.AttrName;
+
+ for (unsigned i = 0, ni = LA.Decls.size(); i < ni; ++i)
Actions.ActOnFinishDelayedAttribute(getCurScope(), LA.Decls[i], Attrs);
- }
if (Tok.getLocation() != OrigLoc) {
// Due to a parsing error, we either went over the cached tokens or
@@ -1164,31 +1162,6 @@ void Parser::ParseLexedAttribute(LatePar
}
}
-/// \brief Wrapper around a case statement checking if AttrName is
-/// one of the thread safety attributes
-bool Parser::IsThreadSafetyAttribute(StringRef AttrName) {
- return llvm::StringSwitch<bool>(AttrName)
- .Case("guarded_by", true)
- .Case("guarded_var", true)
- .Case("pt_guarded_by", true)
- .Case("pt_guarded_var", true)
- .Case("lockable", true)
- .Case("scoped_lockable", true)
- .Case("no_thread_safety_analysis", true)
- .Case("acquired_after", true)
- .Case("acquired_before", true)
- .Case("exclusive_lock_function", true)
- .Case("shared_lock_function", true)
- .Case("exclusive_trylock_function", true)
- .Case("shared_trylock_function", true)
- .Case("unlock_function", true)
- .Case("lock_returned", true)
- .Case("locks_excluded", true)
- .Case("exclusive_locks_required", true)
- .Case("shared_locks_required", true)
- .Default(false);
-}
-
void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=199676&r1=199675&r2=199676&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Jan 20 11:18:35 2014
@@ -1055,7 +1055,7 @@ Decl *Parser::ParseFunctionDefinition(Pa
if (Tok.isNot(tok::equal)) {
AttributeList *DtorAttrs = D.getAttributes();
while (DtorAttrs) {
- if (!IsThreadSafetyAttribute(DtorAttrs->getName()->getName()) &&
+ if (!DtorAttrs->canAppearOnFunctionDefinition() &&
!DtorAttrs->isCXX11Attribute()) {
Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition)
<< DtorAttrs->getName();
Modified: cfe/trunk/lib/Sema/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=199676&r1=199675&r2=199676&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AttributeList.cpp (original)
+++ cfe/trunk/lib/Sema/AttributeList.cpp Mon Jan 20 11:18:35 2014
@@ -150,6 +150,7 @@ struct ParsedAttrInfo {
unsigned HasCustomParsing : 1;
unsigned IsTargetSpecific : 1;
unsigned IsType : 1;
+ unsigned CanAppearOnFuncDef : 1;
bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
const Decl *);
@@ -196,3 +197,7 @@ bool AttributeList::isTypeAttr() const {
bool AttributeList::existsInTarget(llvm::Triple T) const {
return getInfo(*this).ExistsInTarget(T);
}
+
+bool AttributeList::canAppearOnFunctionDefinition() const {
+ return getInfo(*this).CanAppearOnFuncDef;
+}
Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=199676&r1=199675&r2=199676&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Mon Jan 20 11:18:35 2014
@@ -2006,6 +2006,7 @@ static std::string CalculateDiagnostic(c
uint32_t V = StringSwitch<uint32_t>(Name)
.Case("Function", Func)
+ .Case("FunctionDefinition", Func)
.Case("Var", Var)
.Case("ObjCMethod", ObjCMethod)
.Case("ParmVar", Param)
@@ -2081,6 +2082,8 @@ static std::string GetSubjectWithSuffix(
std::string B = R->getName();
if (B == "DeclBase")
return "Decl";
+ else if (B == "FunctionDefinition")
+ return "FunctionDecl";
return B + "Decl";
}
static std::string GenerateCustomAppertainsTo(const Record &Subject,
@@ -2311,6 +2314,24 @@ static std::string GenerateTargetRequire
return FnName;
}
+static bool CanAppearOnFuncDef(const Record &Attr) {
+ // Look at the subjects this function appertains to; if a FunctionDefinition
+ // appears in the list, then this attribute can appear on a function
+ // definition.
+ if (Attr.isValueUnset("Subjects"))
+ return false;
+
+ std::vector<Record *> Subjects = Attr.getValueAsDef("Subjects")->
+ getValueAsListOfDefs("Subjects");
+ for (std::vector<Record *>::const_iterator I = Subjects.begin(),
+ E = Subjects.end(); I != E; ++I) {
+ const Record &Subject = **I;
+ if (Subject.getName() == "FunctionDefinition")
+ return true;
+ }
+ return false;
+}
+
/// Emits the parsed attribute helpers
void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Parsed attribute helpers", OS);
@@ -2346,6 +2367,7 @@ void EmitClangAttrParsedAttrImpl(RecordK
SS << ", " << I->second->getValueAsBit("HasCustomParsing");
SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
SS << ", " << I->second->isSubClassOf("TypeAttr");
+ SS << ", " << CanAppearOnFuncDef(*I->second);
SS << ", " << GenerateAppertainsTo(*I->second, OS);
SS << ", " << GenerateLangOptRequirements(*I->second, OS);
SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
More information about the cfe-commits
mailing list