diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/AttrImpl.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHReaderDecl.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Frontend/PCHWriter.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/AttributeList.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 103 |
6 files changed, 98 insertions, 13 deletions
diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp index fe7cb82b361..423aa065e57 100644 --- a/clang/lib/AST/AttrImpl.cpp +++ b/clang/lib/AST/AttrImpl.cpp @@ -107,6 +107,7 @@ DEF_SIMPLE_ATTR_CLONE(Used) DEF_SIMPLE_ATTR_CLONE(WarnUnusedResult) DEF_SIMPLE_ATTR_CLONE(Weak) DEF_SIMPLE_ATTR_CLONE(WeakImport) +DEF_SIMPLE_ATTR_CLONE(WeakRef) DEF_SIMPLE_ATTR_CLONE(X86ForceAlignArgPointer) Attr* PragmaPackAttr::clone(ASTContext &C) const { @@ -196,5 +197,3 @@ Attr *ReqdWorkGroupSizeAttr::clone(ASTContext &C) const { Attr *MSP430InterruptAttr::clone(ASTContext &C) const { return ::new (C) MSP430InterruptAttr(Number); } - - diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index f819382a936..52366190881 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1327,6 +1327,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) { GA->setLinkage(llvm::Function::DLLExportLinkage); } } else if (D->hasAttr<WeakAttr>() || + D->hasAttr<WeakRefAttr>() || D->hasAttr<WeakImportAttr>()) { GA->setLinkage(llvm::Function::WeakAnyLinkage); } diff --git a/clang/lib/Frontend/PCHReaderDecl.cpp b/clang/lib/Frontend/PCHReaderDecl.cpp index 27349ecbfe5..356bd0726e5 100644 --- a/clang/lib/Frontend/PCHReaderDecl.cpp +++ b/clang/lib/Frontend/PCHReaderDecl.cpp @@ -586,6 +586,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(WarnUnusedResult); SIMPLE_ATTR(Weak); + SIMPLE_ATTR(WeakRef); SIMPLE_ATTR(WeakImport); } diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp index f40facb9f4b..93af7546838 100644 --- a/clang/lib/Frontend/PCHWriter.cpp +++ b/clang/lib/Frontend/PCHWriter.cpp @@ -1916,6 +1916,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::WarnUnusedResult: case Attr::Weak: + case Attr::WeakRef: case Attr::WeakImport: break; } @@ -2335,4 +2336,3 @@ void PCHWriter::AddDeclarationName(DeclarationName Name, RecordData &Record) { break; } } - diff --git a/clang/lib/Parse/AttributeList.cpp b/clang/lib/Parse/AttributeList.cpp index 43722ad0dc9..b96dff573df 100644 --- a/clang/lib/Parse/AttributeList.cpp +++ b/clang/lib/Parse/AttributeList.cpp @@ -57,6 +57,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { // FIXME: Hand generating this is neither smart nor efficient. return llvm::StringSwitch<AttributeList::Kind>(AttrName) .Case("weak", AT_weak) + .Case("weakref", AT_weakref) .Case("pure", AT_pure) .Case("mode", AT_mode) .Case("used", AT_used) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 8178a147513..8a8ad28def2 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -329,6 +329,86 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) NonNullAttr(S.Context, start, size)); } +static bool isStaticVarOrStaticFunciton(Decl *D) { + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + return VD->getStorageClass() == VarDecl::Static; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + return FD->getStorageClass() == FunctionDecl::Static; + return false; +} + +static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + // gcc rejects + // class c { + // static int a __attribute__((weakref ("v2"))); + // static int b() __attribute__((weakref ("f3"))); + // }; + // and ignores the attributes of + // void f(void) { + // static int a __attribute__((weakref ("v2"))); + // } + // we reject them + if (const DeclContext *Ctx = d->getDeclContext()) { + Ctx = Ctx->getLookupContext(); + if (!isa<TranslationUnitDecl>(Ctx) && !isa<NamespaceDecl>(Ctx) ) { + S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) << + dyn_cast<NamedDecl>(d)->getNameAsString(); + return; + } + } + + // The GCC manual says + // + // At present, a declaration to which `weakref' is attached can only + // be `static'. + // + // It also says + // + // Without a TARGET, + // given as an argument to `weakref' or to `alias', `weakref' is + // equivalent to `weak'. + // + // gcc 4.4.1 will accept + // int a7 __attribute__((weakref)); + // as + // int a7 __attribute__((weak)); + // This looks like a bug in gcc. We reject that for now. We should revisit + // it if this behaviour is actually used. + + if (!isStaticVarOrStaticFunciton(d)) { + S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_static) << + dyn_cast<NamedDecl>(d)->getNameAsString(); + return; + } + + // GCC rejects + // static ((alias ("y"), weakref)). + // Should we? How to check that weakref is before or after alias? + + if (Attr.getNumArgs() == 1) { + Expr *Arg = static_cast<Expr*>(Attr.getArg(0)); + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + + if (Str == 0 || Str->isWide()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "weakref" << 1; + return; + } + // GCC will accept anything as the argument of weakref. Should we + // check for an existing decl? + d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString())); + } + + d->addAttr(::new (S.Context) WeakRefAttr()); +} + static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 1) { @@ -777,13 +857,7 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { } /* weak only applies to non-static declarations */ - bool isStatic = false; - if (VarDecl *VD = dyn_cast<VarDecl>(D)) { - isStatic = VD->getStorageClass() == VarDecl::Static; - } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - isStatic = FD->getStorageClass() == FunctionDecl::Static; - } - if (isStatic) { + if (isStaticVarOrStaticFunciton(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_weak_static) << dyn_cast<NamedDecl>(D)->getNameAsString(); return; @@ -1809,6 +1883,7 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S); break; case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; + case AttributeList::AT_weakref: HandleWeakRefAttr (D, Attr, S); break; case AttributeList::AT_weak_import: HandleWeakImportAttr (D, Attr, S); break; case AttributeList::AT_transparent_union: HandleTransparentUnionAttr(D, Attr, S); @@ -1847,9 +1922,17 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, /// ProcessDeclAttributeList - Apply all the decl attributes in the specified /// attribute list to the specified decl, ignoring any type attributes. void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) { - while (AttrList) { - ProcessDeclAttribute(S, D, *AttrList, *this); - AttrList = AttrList->getNext(); + for (const AttributeList* l = AttrList; l; l = l->getNext()) { + ProcessDeclAttribute(S, D, *l, *this); + } + + // GCC accepts + // static int a9 __attribute__((weakref)); + // but that looks really pointless. We reject it. + if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { + Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) << + dyn_cast<NamedDecl>(D)->getNameAsString(); + return; } } |