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