diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-07-02 01:32:16 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-07-02 01:32:16 +0000 |
| commit | d9b9009c611a03b47b40f780de5562b141810682 (patch) | |
| tree | 8b850ec1d6b4ca2c214a840077cd0b9827d0c880 /clang/lib/AST | |
| parent | 27cdf401eaa84e0d4ae82d174ddba6453e882856 (diff) | |
| download | bcm5719-llvm-d9b9009c611a03b47b40f780de5562b141810682.tar.gz bcm5719-llvm-d9b9009c611a03b47b40f780de5562b141810682.zip | |
PR28394: For compatibility with c++11 and c++14, if a static constexpr data
member is redundantly redeclared outside the class definition in code built in
c++17 mode, ensure we emit a non-discardable definition of the data member for
c++11 and c++14 compilations to use.
llvm-svn: 274416
Diffstat (limited to 'clang/lib/AST')
| -rw-r--r-- | clang/lib/AST/ASTContext.cpp | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 564b93453ef..0414c7a9faf 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5146,6 +5146,27 @@ bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const { !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit(); } +ASTContext::InlineVariableDefinitionKind +ASTContext::getInlineVariableDefinitionKind(const VarDecl *VD) const { + if (!VD->isInline()) + return InlineVariableDefinitionKind::None; + + // In almost all cases, it's a weak definition. + auto *First = VD->getFirstDecl(); + if (!First->isConstexpr() || First->isInlineSpecified() || + !VD->isStaticDataMember()) + return InlineVariableDefinitionKind::Weak; + + // If there's a file-context declaration in this translation unit, it's a + // non-discardable definition. + for (auto *D : VD->redecls()) + if (D->getLexicalDeclContext()->isFileContext()) + return InlineVariableDefinitionKind::Strong; + + // If we've not seen one yet, we don't know. + return InlineVariableDefinitionKind::WeakUnknown; +} + static inline std::string charUnitsToString(const CharUnits &CU) { return llvm::itostr(CU.getQuantity()); @@ -8494,9 +8515,21 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, if (Context.isMSStaticDataMemberInlineDefinition(VD)) return GVA_DiscardableODR; - GVALinkage StrongLinkage = GVA_StrongExternal; - if (VD->isInline()) + // Most non-template variables have strong linkage; inline variables are + // linkonce_odr or (occasionally, for compatibility) weak_odr. + GVALinkage StrongLinkage; + switch (Context.getInlineVariableDefinitionKind(VD)) { + case ASTContext::InlineVariableDefinitionKind::None: + StrongLinkage = GVA_StrongExternal; + break; + case ASTContext::InlineVariableDefinitionKind::Weak: + case ASTContext::InlineVariableDefinitionKind::WeakUnknown: StrongLinkage = GVA_DiscardableODR; + break; + case ASTContext::InlineVariableDefinitionKind::Strong: + StrongLinkage = GVA_StrongODR; + break; + } switch (VD->getTemplateSpecializationKind()) { case TSK_Undeclared: |

