diff options
author | Nico Rieck <nico.rieck@gmail.com> | 2014-03-23 21:24:01 +0000 |
---|---|---|
committer | Nico Rieck <nico.rieck@gmail.com> | 2014-03-23 21:24:01 +0000 |
commit | e84f8db709deb6f20b52bbc4b81ea6cc59758588 (patch) | |
tree | 32065b9b2ad29f0f421031e4170929183aef911b /clang/lib/Sema/SemaDecl.cpp | |
parent | 1182600f2077b9420a9e741ecbb49083b034e42d (diff) | |
download | bcm5719-llvm-e84f8db709deb6f20b52bbc4b81ea6cc59758588.tar.gz bcm5719-llvm-e84f8db709deb6f20b52bbc4b81ea6cc59758588.zip |
Treat dllimport globals without explicit storage class as extern
dllimport implies a definition which means the 'extern' keyword is optional
when declaring imported variables.
llvm-svn: 204576
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2e8392fb858..e4511c925fc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4923,6 +4923,31 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) { llvm_unreachable("Unexpected context"); } +static bool hasParsedAttr(Scope *S, const AttributeList *AttrList, + AttributeList::Kind Kind) { + for (const AttributeList *L = AttrList; L; L = L->getNext()) + if (L->getKind() == Kind) + return true; + return false; +} + +static bool hasParsedAttr(Scope *S, const Declarator &PD, + AttributeList::Kind Kind) { + // Check decl attributes on the DeclSpec. + if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), Kind)) + return true; + + // Walk the declarator structure, checking decl attributes that were in a type + // position to the decl itself. + for (unsigned I = 0, E = PD.getNumTypeObjects(); I != E; ++I) { + if (hasParsedAttr(S, PD.getTypeObject(I).getAttrs(), Kind)) + return true; + } + + // Finally, check attributes on the decl itself. + return hasParsedAttr(S, PD.getAttributes(), Kind); +} + /// Adjust the \c DeclContext for a function or variable that might be a /// function-local external declaration. bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) { @@ -4959,6 +4984,12 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec()); + // dllimport globals without explicit storage class are treated as extern. We + // have to change the storage class this early to get the right DeclContext. + if (SC == SC_None && !DC->isRecord() && + hasParsedAttr(S, D, AttributeList::AT_DLLImport)) + SC = SC_Extern; + DeclContext *OriginalDC = DC; bool IsLocalExternDecl = SC == SC_Extern && adjustContextForLocalExternDecl(DC); @@ -5326,6 +5357,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + // Ensure that dllimport globals without explicit storage class are treated as + // extern. The storage class is set above using parsed attributes. Now we can + // check the VarDecl itself. + assert(!NewVD->hasAttr<DLLImportAttr>() || + NewVD->getAttr<DLLImportAttr>()->isInherited() || + NewVD->isStaticDataMember() || NewVD->getStorageClass() != SC_None); + // In auto-retain/release, infer strong retension for variables of // retainable type. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD)) |