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);
}
}