Move the static DeclAttrs map into ASTContext. Fixes <rdar://problem/6983177>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73702 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4af1599..b80142f 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -222,7 +222,7 @@
 unsigned ASTContext::getDeclAlignInBytes(const Decl *D) {
   unsigned Align = Target.getCharWidth();
 
-  if (const AlignedAttr* AA = D->getAttr<AlignedAttr>())
+  if (const AlignedAttr* AA = D->getAttr<AlignedAttr>(*this))
     Align = std::max(Align, AA->getAlignment());
 
   if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
@@ -445,7 +445,7 @@
 
   case Type::Typedef: {
     const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
-    if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) {
+    if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>(*this)) {
       Align = Aligned->getAlignment();
       Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr());
     } else
@@ -505,7 +505,7 @@
 
   // FIXME: Should this override struct packing? Probably we want to
   // take the minimum?
-  if (const PackedAttr *PA = FD->getAttr<PackedAttr>())
+  if (const PackedAttr *PA = FD->getAttr<PackedAttr>(Context))
     FieldPacking = PA->getAlignment();
   
   if (const Expr *BitWidthExpr = FD->getBitWidth()) {
@@ -525,7 +525,7 @@
     FieldAlign = FieldInfo.second;
     if (FieldPacking)
       FieldAlign = std::min(FieldAlign, FieldPacking);
-    if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
+    if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context))
       FieldAlign = std::max(FieldAlign, AA->getAlignment());
     
     // Check if we need to add padding to give the field the correct
@@ -565,7 +565,7 @@
     // is smaller than the specified packing?
     if (FieldPacking)
       FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking));
-    if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>())
+    if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context))
       FieldAlign = std::max(FieldAlign, AA->getAlignment());
     
     // Round up the current record size to the field's alignment boundary.
@@ -731,10 +731,10 @@
   }
 
   unsigned StructPacking = 0;
-  if (const PackedAttr *PA = D->getAttr<PackedAttr>())
+  if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this))
     StructPacking = PA->getAlignment();
 
-  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
+  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this))
     NewEntry->SetAlignment(std::max(NewEntry->getAlignment(), 
                                     AA->getAlignment()));
 
@@ -783,10 +783,10 @@
   bool IsUnion = D->isUnion();
 
   unsigned StructPacking = 0;
-  if (const PackedAttr *PA = D->getAttr<PackedAttr>())
+  if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this))
     StructPacking = PA->getAlignment();
 
-  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
+  if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this))
     NewEntry->SetAlignment(std::max(NewEntry->getAlignment(), 
                                     AA->getAlignment()));
 
@@ -2782,7 +2782,7 @@
 bool ASTContext::isObjCNSObjectType(QualType Ty) const {
   if (TypedefType *TDT = dyn_cast<TypedefType>(Ty)) {
     if (TypedefDecl *TD = TDT->getDecl())
-      if (TD->getAttr<ObjCNSObjectAttr>())
+      if (TD->getAttr<ObjCNSObjectAttr>(*const_cast<ASTContext*>(this)))
         return true;
   }
   return false;  
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index a3e406b..b2b643a 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -380,13 +380,14 @@
   // In C, any non-static, non-overloadable function has external
   // linkage.
   if (!Context.getLangOptions().CPlusPlus)
-    return getStorageClass() != Static && !getAttr<OverloadableAttr>();
+    return getStorageClass() != Static && !getAttr<OverloadableAttr>(Context);
 
   for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); 
        DC = DC->getParent()) {
     if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))  {
       if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
-        return getStorageClass() != Static && !getAttr<OverloadableAttr>();
+        return getStorageClass() != Static && 
+               !getAttr<OverloadableAttr>(Context);
 
       break;
     }
@@ -451,7 +452,7 @@
   if (isa<LinkageSpecDecl>(getDeclContext()) &&
       cast<LinkageSpecDecl>(getDeclContext())->getLanguage() 
         == LinkageSpecDecl::lang_c &&
-      !getAttr<OverloadableAttr>())
+      !getAttr<OverloadableAttr>(Context))
     return BuiltinID;
 
   // Not a builtin
@@ -496,25 +497,25 @@
   return NumRequiredArgs;
 }
 
-bool FunctionDecl::hasActiveGNUInlineAttribute() const {
-  if (!isInline() || !hasAttr<GNUInlineAttr>())
+bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const {
+  if (!isInline() || !hasAttr<GNUInlineAttr>(Context))
     return false;
 
   for (const FunctionDecl *FD = getPreviousDeclaration(); FD; 
        FD = FD->getPreviousDeclaration()) {
-    if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>())
+    if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>(Context))
       return false;
   }
 
   return true;
 }
 
-bool FunctionDecl::isExternGNUInline() const {
-  if (!hasActiveGNUInlineAttribute())
+bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
+  if (!hasActiveGNUInlineAttribute(Context))
     return false;
 
   for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration())
-    if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>())
+    if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>(Context))
       return true;
 
   return false;
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index a39a506..b83a503 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -38,12 +38,6 @@
 
 static bool StatSwitch = false;
 
-// This keeps track of all decl attributes. Since so few decls have attrs, we
-// keep them in a hash map instead of wasting space in the Decl class.
-typedef llvm::DenseMap<const Decl*, Attr*> DeclAttrMapTy;
-
-static DeclAttrMapTy *DeclAttrs = 0;
-
 const char *Decl::getDeclKindName() const {
   switch (DeclKind) {
   default: assert(0 && "Declaration not in DeclNodes.def!");
@@ -224,11 +218,8 @@
   }
 }
 
-void Decl::addAttr(Attr *NewAttr) {
-  if (!DeclAttrs)
-    DeclAttrs = new DeclAttrMapTy();
-  
-  Attr *&ExistingAttr = (*DeclAttrs)[this];
+void Decl::addAttr(ASTContext &Context, Attr *NewAttr) {
+  Attr *&ExistingAttr = Context.getDeclAttrs(this);
 
   NewAttr->setNext(ExistingAttr);
   ExistingAttr = NewAttr;
@@ -236,25 +227,19 @@
   HasAttrs = true;
 }
 
-void Decl::invalidateAttrs() {
+void Decl::invalidateAttrs(ASTContext &Context) {
   if (!HasAttrs) return;
-
+  
   HasAttrs = false;
-  (*DeclAttrs)[this] = 0;
-  DeclAttrs->erase(this);
-
-  if (DeclAttrs->empty()) {
-    delete DeclAttrs;
-    DeclAttrs = 0;
-  }
+  Context.eraseDeclAttrs(this);
 }
 
-const Attr *Decl::getAttrsImpl() const {
+const Attr *Decl::getAttrsImpl(ASTContext &Context) const {
   assert(HasAttrs && "getAttrs() should verify this!"); 
-  return (*DeclAttrs)[this];
+  return Context.getDeclAttrs(this);
 }
 
-void Decl::swapAttrs(Decl *RHS) {
+void Decl::swapAttrs(ASTContext &Context, Decl *RHS) {
   bool HasLHSAttr = this->HasAttrs;
   bool HasRHSAttr = RHS->HasAttrs;
   
@@ -263,17 +248,17 @@
   
   // If 'this' has no attrs, swap the other way.
   if (!HasLHSAttr)
-    return RHS->swapAttrs(this);
+    return RHS->swapAttrs(Context, this);
   
   // Handle the case when both decls have attrs.
   if (HasRHSAttr) {
-    std::swap((*DeclAttrs)[this], (*DeclAttrs)[RHS]);
+    std::swap(Context.getDeclAttrs(this), Context.getDeclAttrs(RHS));
     return;
   }
   
   // Otherwise, LHS has an attr and RHS doesn't.
-  (*DeclAttrs)[RHS] = (*DeclAttrs)[this];
-  (*DeclAttrs).erase(this);
+  Context.getDeclAttrs(RHS) = Context.getDeclAttrs(this);
+  Context.eraseDeclAttrs(this);
   this->HasAttrs = false;
   RHS->HasAttrs = true;
 }
@@ -282,12 +267,8 @@
 void Decl::Destroy(ASTContext &C) {
   // Free attributes for this decl.
   if (HasAttrs) {
-    DeclAttrMapTy::iterator it = DeclAttrs->find(this);
-    assert(it != DeclAttrs->end() && "No attrs found but HasAttrs is true!");
-  
-    // release attributes.
-    it->second->Destroy(C);
-    invalidateAttrs();
+    C.getDeclAttrs(this)->Destroy(C);
+    invalidateAttrs(C);
     HasAttrs = false;
   }
   
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 309be41..eb4136c 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -456,7 +456,7 @@
 /// with location to warn on and the source range[s] to report with the
 /// warning.
 bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
-                                  SourceRange &R2) const {
+                                  SourceRange &R2, ASTContext &Context) const {
   // Don't warn if the expr is type dependent. The type could end up
   // instantiating to void.
   if (isTypeDependent())
@@ -469,7 +469,7 @@
     return true;
   case ParenExprClass:
     return cast<ParenExpr>(this)->getSubExpr()->
-      isUnusedResultAWarning(Loc, R1, R2);
+      isUnusedResultAWarning(Loc, R1, R2, Context);
   case UnaryOperatorClass: {
     const UnaryOperator *UO = cast<UnaryOperator>(this);
     
@@ -492,7 +492,7 @@
         return false;
       break;
     case UnaryOperator::Extension:
-      return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+      return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
     }
     Loc = UO->getOperatorLoc();
     R1 = UO->getSubExpr()->getSourceRange();
@@ -502,8 +502,8 @@
     const BinaryOperator *BO = cast<BinaryOperator>(this);
     // Consider comma to have side effects if the LHS or RHS does.
     if (BO->getOpcode() == BinaryOperator::Comma)
-      return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2) ||
-             BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2);
+      return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context) ||
+             BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context);
       
     if (BO->isAssignmentOp())
       return false;
@@ -519,9 +519,10 @@
     // The condition must be evaluated, but if either the LHS or RHS is a
     // warning, warn about them.
     const ConditionalOperator *Exp = cast<ConditionalOperator>(this);
-    if (Exp->getLHS() && Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2))
+    if (Exp->getLHS() && 
+        Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context))
       return true;
-    return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2);
+    return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context);
   }
 
   case MemberExprClass:
@@ -554,8 +555,8 @@
       // If the callee has attribute pure, const, or warn_unused_result, warn
       // about it. void foo() { strlen("bar"); } should warn.
       if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeDRE->getDecl()))
-        if (FD->getAttr<WarnUnusedResultAttr>() ||
-            FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) {
+        if (FD->getAttr<WarnUnusedResultAttr>(Context) ||
+            FD->getAttr<PureAttr>(Context) || FD->getAttr<ConstAttr>(Context)) {
           Loc = CE->getCallee()->getLocStart();
           R1 = CE->getCallee()->getSourceRange();
           
@@ -578,7 +579,7 @@
     const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt();
     if (!CS->body_empty())
       if (const Expr *E = dyn_cast<Expr>(CS->body_back()))
-        return E->isUnusedResultAWarning(Loc, R1, R2);
+        return E->isUnusedResultAWarning(Loc, R1, R2, Context);
     
     Loc = cast<StmtExpr>(this)->getLParenLoc();
     R1 = getSourceRange();
@@ -588,8 +589,8 @@
     // If this is a cast to void, check the operand.  Otherwise, the result of
     // the cast is unused.
     if (getType()->isVoidType())
-      return cast<CastExpr>(this)->getSubExpr()->isUnusedResultAWarning(Loc,
-                                                                        R1, R2);
+      return cast<CastExpr>(this)->getSubExpr()
+               ->isUnusedResultAWarning(Loc, R1, R2, Context);
     Loc = cast<CStyleCastExpr>(this)->getLParenLoc();
     R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange();
     return true;
@@ -597,8 +598,8 @@
     // If this is a cast to void, check the operand.  Otherwise, the result of
     // the cast is unused.
     if (getType()->isVoidType())
-      return cast<CastExpr>(this)->getSubExpr()->isUnusedResultAWarning(Loc,
-                                                                        R1, R2);
+      return cast<CastExpr>(this)->getSubExpr()
+               ->isUnusedResultAWarning(Loc, R1, R2, Context);
     Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc();
     R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange();
     return true;
@@ -606,11 +607,11 @@
   case ImplicitCastExprClass:
     // Check the operand, since implicit casts are inserted by Sema
     return cast<ImplicitCastExpr>(this)
-      ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+      ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
 
   case CXXDefaultArgExprClass:
     return cast<CXXDefaultArgExpr>(this)
-      ->getExpr()->isUnusedResultAWarning(Loc, R1, R2);
+      ->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
 
   case CXXNewExprClass:
     // FIXME: In theory, there might be new expressions that don't have side
@@ -619,7 +620,7 @@
     return false;
   case CXXExprWithTemporariesClass:
     return cast<CXXExprWithTemporaries>(this)
-      ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2);
+      ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context);
   }
 }