[cfe-commits] r148595 - in /cfe/trunk: include/clang/AST/Attr.h include/clang/Sema/Sema.h include/clang/Sema/Template.h lib/Parse/ParseDecl.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/warn-thread-safety-analysis.cpp utils/TableGen/ClangAttrEmitter.cpp

DeLesley Hutchins delesley at google.com
Fri Jan 20 14:50:54 PST 2012


Author: delesley
Date: Fri Jan 20 16:50:54 2012
New Revision: 148595

URL: http://llvm.org/viewvc/llvm-project?rev=148595&view=rev
Log:
Delayed template instantiation of late-parsed attributes.

Modified:
    cfe/trunk/include/clang/AST/Attr.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Sema/Template.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=148595&r1=148594&r2=148595&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Fri Jan 20 16:50:54 2012
@@ -104,6 +104,8 @@
   // Clone this attribute.
   virtual Attr* clone(ASTContext &C) const = 0;
 
+  virtual bool isLateParsed() const { return false; }
+
   // Pretty print this attribute.
   virtual void printPretty(llvm::raw_ostream &OS, ASTContext &C) const = 0;
 

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=148595&r1=148594&r2=148595&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jan 20 16:50:54 2012
@@ -5131,8 +5131,22 @@
                    TemplateSpecializationKind TSK,
                    bool Complain = true);
 
+  struct LateInstantiatedAttribute {
+    const Attr *TmplAttr;
+    LocalInstantiationScope *Scope;
+    Decl *NewDecl;
+
+    LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S,
+                              Decl *D)
+      : TmplAttr(A), Scope(S), NewDecl(D)
+    { }
+  };
+  typedef SmallVector<LateInstantiatedAttribute, 16> LateInstantiatedAttrVec;
+
   void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
-                        const Decl *Pattern, Decl *Inst);
+                        const Decl *Pattern, Decl *Inst,
+                        LateInstantiatedAttrVec *LateAttrs = 0,
+                        LocalInstantiationScope *OuterMostScope = 0);
 
   bool
   InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,

Modified: cfe/trunk/include/clang/Sema/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=148595&r1=148594&r2=148595&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Template.h (original)
+++ cfe/trunk/include/clang/Sema/Template.h Fri Jan 20 16:50:54 2012
@@ -268,6 +268,50 @@
       Exited = true;
     }
 
+    /// \brief Clone this scope, and all outer scopes, down to the given
+    /// outermost scope.
+    LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) {
+      if (this == Outermost) return this;
+      LocalInstantiationScope *newScope =
+        new LocalInstantiationScope(SemaRef, CombineWithOuterScope);
+
+      newScope->Outer = 0;
+      if (Outer)
+        newScope->Outer = Outer->cloneScopes(Outermost);
+
+      newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
+      newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
+      newScope->NumArgsInPartiallySubstitutedPack =
+        NumArgsInPartiallySubstitutedPack;
+
+      for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end();
+           I != E; ++I) {
+        const Decl *D = I->first;
+        llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
+          newScope->LocalDecls[D];
+        if (I->second.is<Decl *>()) {
+          Stored = I->second.get<Decl *>();
+        } else {
+          DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>();
+          DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack);
+          Stored = NewPack;
+          newScope->ArgumentPacks.push_back(NewPack);
+        }
+      }
+      return newScope;
+    }
+
+    /// \brief deletes the given scope, and all otuer scopes, down to the
+    /// given outermost scope.
+    static void deleteScopes(LocalInstantiationScope *Scope,
+                             LocalInstantiationScope *Outermost) {
+      while (Scope && Scope != Outermost) {
+        LocalInstantiationScope *Out = Scope->Outer;
+        delete Scope;
+        Scope = Out;
+      }
+    }
+
     /// \brief Find the instantiation of the declaration D within the current
     /// instantiation scope.
     ///
@@ -314,6 +358,8 @@
     Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
     DeclContext *Owner;
     const MultiLevelTemplateArgumentList &TemplateArgs;
+    Sema::LateInstantiatedAttrVec* LateAttrs;
+    LocalInstantiationScope *StartingScope;
 
     /// \brief A list of out-of-line class template partial
     /// specializations that will need to be instantiated after the
@@ -326,7 +372,7 @@
     TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
                              const MultiLevelTemplateArgumentList &TemplateArgs)
       : SemaRef(SemaRef), SubstIndex(SemaRef, -1), Owner(Owner), 
-        TemplateArgs(TemplateArgs) { }
+        TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0) { }
 
     // FIXME: Once we get closer to completion, replace these manually-written
     // declarations with automatically-generated ones from
@@ -382,6 +428,21 @@
       return 0;
     }
     
+    // Enable late instantiation of attributes.  Late instantiated attributes
+    // will be stored in LA.
+    void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) {
+      LateAttrs = LA;
+      StartingScope = SemaRef.CurrentInstantiationScope;
+    }
+
+    // Disable late instantiation of attributes.
+    void disableLateAttributeInstantiation() {
+      LateAttrs = 0;
+      StartingScope = 0;
+    }
+
+    LocalInstantiationScope *getStartingScope() const { return StartingScope; }
+
     typedef 
       SmallVectorImpl<std::pair<ClassTemplateDecl *,
                                      ClassTemplatePartialSpecializationDecl *> >

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=148595&r1=148594&r2=148595&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Jan 20 16:50:54 2012
@@ -857,7 +857,7 @@
     ConsumeToken(); // Eat the comma, move to the next argument
   }
   // Match the ')'.
-  if (ArgExprsOk && !T.consumeClose() && ArgExprs.size() > 0) {
+  if (ArgExprsOk && !T.consumeClose()) {
     Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(),
                  ArgExprs.take(), ArgExprs.size());
   }

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=148595&r1=148594&r2=148595&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Jan 20 16:50:54 2012
@@ -1654,6 +1654,10 @@
   return Invalid;
 }
 
+// Defined via #include from SemaTemplateInstantiateDecl.cpp
+Attr* instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S,
+        const MultiLevelTemplateArgumentList &TemplateArgs);
+
 /// \brief Instantiate the definition of a class from a given pattern.
 ///
 /// \param PointOfInstantiation The point of instantiation within the
@@ -1763,6 +1767,10 @@
   SmallVector<Decl*, 4> Fields;
   SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4>
     FieldsWithMemberInitializers;
+  // Delay instantiation of late parsed attributes.
+  LateInstantiatedAttrVec LateAttrs;
+  Instantiator.enableLateAttributeInstantiation(&LateAttrs);
+
   for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
          MemberEnd = Pattern->decls_end();
        Member != MemberEnd; ++Member) {
@@ -1822,6 +1830,21 @@
     }
   }
 
+  // Instantiate late parsed attributes, and attach them to their decls.
+  // See Sema::InstantiateAttrs
+  for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
+       E = LateAttrs.end(); I != E; ++I) {
+    assert(CurrentInstantiationScope == Instantiator.getStartingScope());
+    CurrentInstantiationScope = I->Scope;
+    Attr *NewAttr =
+      instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
+    I->NewDecl->addAttr(NewAttr);
+    LocalInstantiationScope::deleteScopes(I->Scope,
+                                          Instantiator.getStartingScope());
+  }
+  Instantiator.disableLateAttributeInstantiation();
+  LateAttrs.clear();
+
   if (!FieldsWithMemberInitializers.empty())
     ActOnFinishDelayedMemberInitializers(Instantiation);
 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=148595&r1=148594&r2=148595&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Jan 20 16:50:54 2012
@@ -61,10 +61,13 @@
 #include "clang/Sema/AttrTemplateInstantiate.inc"
 
 void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
-                            const Decl *Tmpl, Decl *New) {
+                            const Decl *Tmpl, Decl *New,
+                            LateInstantiatedAttrVec *LateAttrs,
+                            LocalInstantiationScope *OuterMostScope) {
   for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
        i != e; ++i) {
     const Attr *TmplAttr = *i;
+
     // FIXME: This should be generalized to more than just the AlignedAttr.
     if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
       if (Aligned->isAlignmentDependent()) {
@@ -89,9 +92,18 @@
       }
     }
 
-    Attr *NewAttr =
-      instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs);
-    New->addAttr(NewAttr);
+    if (TmplAttr->isLateParsed() && LateAttrs) {
+      // Late parsed attributes must be instantiated and attached after the
+      // enclosing class has been instantiated.  See Sema::InstantiateClass.
+      LocalInstantiationScope *Saved = 0;
+      if (CurrentInstantiationScope)
+        Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope);
+      LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New));
+    } else {
+      Attr *NewAttr =
+        instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs);
+      New->addAttr(NewAttr);
+    }
   }
 }
 
@@ -495,7 +507,7 @@
     return 0;
   }
 
-  SemaRef.InstantiateAttrs(TemplateArgs, D, Field);
+  SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope);
 
   if (Invalid)
     Field->setInvalidDecl();
@@ -2378,7 +2390,8 @@
   // Get the definition. Leaves the variable unchanged if undefined.
   Tmpl->isDefined(Definition);
 
-  SemaRef.InstantiateAttrs(TemplateArgs, Definition, New);
+  SemaRef.InstantiateAttrs(TemplateArgs, Definition, New,
+                           LateAttrs, StartingScope);
 
   return false;
 }

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=148595&r1=148594&r2=148595&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:50:54 2012
@@ -1051,14 +1051,12 @@
  public:
   void func(T x) {
     mu_.Lock();
-    // count_ = x;
+    count_ = x;
     mu_.Unlock();
   }
 
  private:
-  // FIXME: This test passed earlier only because thread safety was turned
-  // off for templates.
-  // T count_ GUARDED_BY(mu_);
+  T count_ GUARDED_BY(mu_);
   Bar<T> bar_;
   Mutex mu_;
 };
@@ -1790,27 +1788,15 @@
   // Test dependent guarded_by
   T data GUARDED_BY(mu_);
 
-  void foo() {
-    mu_.Lock();
+  void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
     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() {
@@ -1842,13 +1828,50 @@
   cell.data = 0; // \
     // expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
   cell.foo();
+  cell.mu_.Lock();
+  cell.fooEx();
+  cell.mu_.Unlock();
+}
+
+
+template <class T>
+class CellDelayed {
+public:
+  // Test dependent guarded_by
+  T data GUARDED_BY(mu_);
+
+  void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
+    this->data = other->data;
+  }
+
+  template <class T2>
+  void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
+    this->data = otherT->data;
+  }
 
-  // FIXME: This doesn't work yet
-  // CellDelayed<int> celld;
-  // celld.foo();
+  void foo() {
+    mu_.Lock();
+    data = 0;
+    mu_.Unlock();
+  }
+
+  Mutex mu_;
+};
+
+void testDelayed() {
+  CellDelayed<int> celld;
+  CellDelayed<int> celld2;
+  celld.foo();
+  celld.mu_.Lock();
+  celld2.mu_.Lock();
+
+  celld.fooEx(&celld2);
+  celld.fooExT(&celld2);
+
+  celld2.mu_.Unlock();
+  celld.mu_.Unlock();
 }
 
 };  // end namespace TestTemplateAttributeInstantiation
 
 
-

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=148595&r1=148594&r2=148595&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Fri Jan 20 16:50:54 2012
@@ -349,7 +349,7 @@
          << "Size;\n";
       OS << "  }\n";
       OS << "  unsigned " << getLowerName() << "_size() const {\n"
-         << "    return " << getLowerName() << "Size;\n;";
+         << "    return " << getLowerName() << "Size;\n";
       OS << "  }";
     }
     void writeCloneArgs(raw_ostream &OS) const {
@@ -709,6 +709,11 @@
        << "attr::" << R.getName() << "; }\n";
     OS << "  static bool classof(const " << R.getName()
        << "Attr *) { return true; }\n";
+
+    bool LateParsed = R.getValueAsBit("LateParsed");
+    OS << "  virtual bool isLateParsed() const { return "
+       << LateParsed << "; }\n";
+
     OS << "};\n\n";
   }
 





More information about the cfe-commits mailing list