forked from OSchip/llvm-project
[Modules TS] Module ownership semantics for redeclarations.
When declaring an entity in the "purview" of a module, it's never a redeclaration of an entity in the purview of a default module or in no module ("in the global module"). Don't consider those other declarations as possible redeclaration targets if they're not visible, and reject any cases where we pick a prior visible declaration that violates this rule. llvm-svn: 315251
This commit is contained in:
parent
8b53f7ca6d
commit
b87720b77a
|
@ -339,6 +339,12 @@ public:
|
|||
return clang::isExternallyVisible(getLinkageInternal());
|
||||
}
|
||||
|
||||
/// Determine whether this declaration can be redeclared in a
|
||||
/// different translation unit.
|
||||
bool isExternallyDeclarable() const {
|
||||
return isExternallyVisible() && !getOwningModuleForLinkage();
|
||||
}
|
||||
|
||||
/// \brief Determines the visibility of this entity.
|
||||
Visibility getVisibility() const {
|
||||
return getLinkageAndVisibility().getVisibility();
|
||||
|
@ -379,10 +385,6 @@ public:
|
|||
return hasCachedLinkage();
|
||||
}
|
||||
|
||||
/// Get the module that owns this declaration for linkage purposes.
|
||||
/// There only ever is such a module under the C++ Modules TS.
|
||||
Module *getOwningModuleForLinkage() const;
|
||||
|
||||
/// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
|
||||
/// the underlying named decl.
|
||||
NamedDecl *getUnderlyingDecl() {
|
||||
|
|
|
@ -738,6 +738,10 @@ public:
|
|||
return isFromASTFile() ? getImportedOwningModule() : getLocalOwningModule();
|
||||
}
|
||||
|
||||
/// Get the module that owns this declaration for linkage purposes.
|
||||
/// There only ever is such a module under the C++ Modules TS.
|
||||
Module *getOwningModuleForLinkage() const;
|
||||
|
||||
/// \brief Determine whether this declaration might be hidden from name
|
||||
/// lookup. Note that the declaration might be visible even if this returns
|
||||
/// \c false, if the owning module is visible within the query context.
|
||||
|
|
|
@ -4801,6 +4801,9 @@ def err_thread_non_thread : Error<
|
|||
def err_thread_thread_different_kind : Error<
|
||||
"thread-local declaration of %0 with %select{static|dynamic}1 initialization "
|
||||
"follows declaration with %select{dynamic|static}1 initialization">;
|
||||
def err_mismatched_owning_module : Error<
|
||||
"declaration of %0 in %select{the global module|module %2}1 follows "
|
||||
"declaration in %select{the global module|module %4}3">;
|
||||
def err_redefinition_different_type : Error<
|
||||
"redefinition of %0 with a different type%diff{: $ vs $|}1,2">;
|
||||
def err_redefinition_different_kind : Error<
|
||||
|
|
|
@ -139,6 +139,7 @@ public:
|
|||
LookupKind(LookupKind),
|
||||
IDNS(0),
|
||||
Redecl(Redecl != Sema::NotForRedeclaration),
|
||||
ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
|
||||
HideTags(true),
|
||||
Diagnose(Redecl == Sema::NotForRedeclaration),
|
||||
AllowHidden(false),
|
||||
|
@ -161,6 +162,7 @@ public:
|
|||
LookupKind(LookupKind),
|
||||
IDNS(0),
|
||||
Redecl(Redecl != Sema::NotForRedeclaration),
|
||||
ExternalRedecl(Redecl == Sema::ForExternalRedeclaration),
|
||||
HideTags(true),
|
||||
Diagnose(Redecl == Sema::NotForRedeclaration),
|
||||
AllowHidden(false),
|
||||
|
@ -181,6 +183,7 @@ public:
|
|||
LookupKind(Other.LookupKind),
|
||||
IDNS(Other.IDNS),
|
||||
Redecl(Other.Redecl),
|
||||
ExternalRedecl(Other.ExternalRedecl),
|
||||
HideTags(Other.HideTags),
|
||||
Diagnose(false),
|
||||
AllowHidden(Other.AllowHidden),
|
||||
|
@ -201,7 +204,9 @@ public:
|
|||
SemaPtr(std::move(Other.SemaPtr)), NameInfo(std::move(Other.NameInfo)),
|
||||
NameContextRange(std::move(Other.NameContextRange)),
|
||||
LookupKind(std::move(Other.LookupKind)), IDNS(std::move(Other.IDNS)),
|
||||
Redecl(std::move(Other.Redecl)), HideTags(std::move(Other.HideTags)),
|
||||
Redecl(std::move(Other.Redecl)),
|
||||
ExternalRedecl(std::move(Other.ExternalRedecl)),
|
||||
HideTags(std::move(Other.HideTags)),
|
||||
Diagnose(std::move(Other.Diagnose)),
|
||||
AllowHidden(std::move(Other.AllowHidden)),
|
||||
Shadowed(std::move(Other.Shadowed)) {
|
||||
|
@ -221,6 +226,7 @@ public:
|
|||
LookupKind = std::move(Other.LookupKind);
|
||||
IDNS = std::move(Other.IDNS);
|
||||
Redecl = std::move(Other.Redecl);
|
||||
ExternalRedecl = std::move(Other.ExternalRedecl);
|
||||
HideTags = std::move(Other.HideTags);
|
||||
Diagnose = std::move(Other.Diagnose);
|
||||
AllowHidden = std::move(Other.AllowHidden);
|
||||
|
@ -265,6 +271,17 @@ public:
|
|||
return Redecl;
|
||||
}
|
||||
|
||||
/// True if this lookup is just looking for an existing declaration to link
|
||||
/// against a declaration with external linkage.
|
||||
bool isForExternalRedeclaration() const {
|
||||
return ExternalRedecl;
|
||||
}
|
||||
|
||||
Sema::RedeclarationKind redeclarationKind() const {
|
||||
return ExternalRedecl ? Sema::ForExternalRedeclaration :
|
||||
Redecl ? Sema::ForVisibleRedeclaration : Sema::NotForRedeclaration;
|
||||
}
|
||||
|
||||
/// \brief Specify whether hidden declarations are visible, e.g.,
|
||||
/// for recovery reasons.
|
||||
void setAllowHidden(bool AH) {
|
||||
|
@ -275,7 +292,7 @@ public:
|
|||
/// declarations, such as those in modules that have not yet been imported.
|
||||
bool isHiddenDeclarationVisible(NamedDecl *ND) const {
|
||||
return AllowHidden ||
|
||||
(isForRedeclaration() && ND->hasExternalFormalLinkage());
|
||||
(isForExternalRedeclaration() && ND->isExternallyDeclarable());
|
||||
}
|
||||
|
||||
/// Sets whether tag declarations should be hidden by non-tag
|
||||
|
@ -556,7 +573,8 @@ public:
|
|||
|
||||
/// \brief Change this lookup's redeclaration kind.
|
||||
void setRedeclarationKind(Sema::RedeclarationKind RK) {
|
||||
Redecl = RK;
|
||||
Redecl = (RK != Sema::NotForRedeclaration);
|
||||
ExternalRedecl = (RK == Sema::ForExternalRedeclaration);
|
||||
configure();
|
||||
}
|
||||
|
||||
|
@ -719,6 +737,7 @@ private:
|
|||
unsigned IDNS; // set by configure()
|
||||
|
||||
bool Redecl;
|
||||
bool ExternalRedecl;
|
||||
|
||||
/// \brief True if tag declarations should be hidden if non-tags
|
||||
/// are present
|
||||
|
|
|
@ -285,15 +285,21 @@ class Sema {
|
|||
|
||||
bool isVisibleSlow(const NamedDecl *D);
|
||||
|
||||
/// Determine whether two declarations should be linked together, given that
|
||||
/// the old declaration might not be visible and the new declaration might
|
||||
/// not have external linkage.
|
||||
bool shouldLinkPossiblyHiddenDecl(const NamedDecl *Old,
|
||||
const NamedDecl *New) {
|
||||
// We are about to link these. It is now safe to compute the linkage of
|
||||
// the new decl. If the new decl has external linkage, we will
|
||||
// link it with the hidden decl (which also has external linkage) and
|
||||
// it will keep having external linkage. If it has internal linkage, we
|
||||
// will not link it. Since it has no previous decls, it will remain
|
||||
// with internal linkage.
|
||||
return isVisible(Old) || New->isExternallyVisible();
|
||||
if (isVisible(Old))
|
||||
return true;
|
||||
// See comment in below overload for why it's safe to compute the linkage
|
||||
// of the new declaration here.
|
||||
if (New->isExternallyDeclarable()) {
|
||||
assert(Old->isExternallyDeclarable() &&
|
||||
"should not have found a non-externally-declarable previous decl");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New);
|
||||
|
||||
|
@ -3035,10 +3041,22 @@ public:
|
|||
/// purpose of redeclaring the name.
|
||||
NotForRedeclaration = 0,
|
||||
/// \brief The lookup results will be used for redeclaration of a name,
|
||||
/// if an entity by that name already exists.
|
||||
ForRedeclaration
|
||||
/// if an entity by that name already exists and is visible.
|
||||
ForVisibleRedeclaration,
|
||||
/// \brief The lookup results will be used for redeclaration of a name
|
||||
/// with external linkage; non-visible lookup results with external linkage
|
||||
/// may also be found.
|
||||
ForExternalRedeclaration
|
||||
};
|
||||
|
||||
RedeclarationKind forRedeclarationInCurContext() {
|
||||
// A declaration with an owning module for linkage can never link against
|
||||
// anything that is not visible.
|
||||
if (cast<Decl>(CurContext)->getOwningModuleForLinkage())
|
||||
return ForVisibleRedeclaration;
|
||||
return ForExternalRedeclaration;
|
||||
}
|
||||
|
||||
/// \brief The possible outcomes of name lookup for a literal operator.
|
||||
enum LiteralOperatorLookupResult {
|
||||
/// \brief The lookup resulted in an error.
|
||||
|
@ -3266,6 +3284,8 @@ public:
|
|||
void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
|
||||
bool ConsiderLinkage, bool AllowInlineNamespace);
|
||||
|
||||
bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old);
|
||||
|
||||
void DiagnoseAmbiguousLookup(LookupResult &Result);
|
||||
//@}
|
||||
|
||||
|
|
|
@ -515,6 +515,7 @@ static bool isSingleLineLanguageLinkage(const Decl &D) {
|
|||
}
|
||||
|
||||
static bool isExportedFromModuleIntefaceUnit(const NamedDecl *D) {
|
||||
// FIXME: Handle isModulePrivate.
|
||||
switch (D->getModuleOwnershipKind()) {
|
||||
case Decl::ModuleOwnershipKind::Unowned:
|
||||
case Decl::ModuleOwnershipKind::ModulePrivate:
|
||||
|
@ -546,7 +547,8 @@ static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
|
|||
// declaration has module linkage.
|
||||
if (auto *M = D->getOwningModule())
|
||||
if (M->Kind == Module::ModuleInterfaceUnit)
|
||||
if (!isExportedFromModuleIntefaceUnit(D))
|
||||
if (!isExportedFromModuleIntefaceUnit(
|
||||
cast<NamedDecl>(D->getCanonicalDecl())))
|
||||
return LinkageInfo(ModuleLinkage, DefaultVisibility, false);
|
||||
|
||||
return LinkageInfo::external();
|
||||
|
@ -1393,7 +1395,7 @@ LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
|
|||
: NamedDecl::VisibilityForValue));
|
||||
}
|
||||
|
||||
Module *NamedDecl::getOwningModuleForLinkage() const {
|
||||
Module *Decl::getOwningModuleForLinkage() const {
|
||||
Module *M = getOwningModule();
|
||||
if (!M)
|
||||
return nullptr;
|
||||
|
@ -1411,7 +1413,15 @@ Module *NamedDecl::getOwningModuleForLinkage() const {
|
|||
// for linkage purposes. But internal linkage declarations in the global
|
||||
// module fragment of a particular module are owned by that module for
|
||||
// linkage purposes.
|
||||
return hasExternalFormalLinkage() ? nullptr : M->Parent;
|
||||
bool InternalLinkage;
|
||||
if (auto *ND = dyn_cast<NamedDecl>(this))
|
||||
InternalLinkage = !ND->hasExternalFormalLinkage();
|
||||
else {
|
||||
auto *NSD = dyn_cast<NamespaceDecl>(this);
|
||||
InternalLinkage = (NSD && NSD->isAnonymousNamespace()) ||
|
||||
isInAnonymousNamespace();
|
||||
}
|
||||
return InternalLinkage ? M->Parent : nullptr;
|
||||
}
|
||||
|
||||
llvm_unreachable("unknown module kind");
|
||||
|
|
|
@ -315,12 +315,11 @@ bool Decl::isLexicallyWithinFunctionOrMethod() const {
|
|||
}
|
||||
|
||||
bool Decl::isInAnonymousNamespace() const {
|
||||
const DeclContext *DC = getDeclContext();
|
||||
do {
|
||||
for (const DeclContext *DC = getDeclContext(); DC; DC = DC->getParent()) {
|
||||
if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC))
|
||||
if (ND->isAnonymousNamespace())
|
||||
return true;
|
||||
} while ((DC = DC->getParent()));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C,
|
|||
CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
|
||||
DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||
CXXRecordDecl* PrevDecl,
|
||||
CXXRecordDecl *PrevDecl,
|
||||
bool DelayTypeCreation) {
|
||||
CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc,
|
||||
IdLoc, Id, PrevDecl);
|
||||
|
|
|
@ -1448,6 +1448,46 @@ void Sema::FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
|
|||
F.done();
|
||||
}
|
||||
|
||||
/// We've determined that \p New is a redeclaration of \p Old. Check that they
|
||||
/// have compatible owning modules.
|
||||
bool Sema::CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old) {
|
||||
// FIXME: The Modules TS is not clear about how friend declarations are
|
||||
// to be treated. It's not meaningful to have different owning modules for
|
||||
// linkage in redeclarations of the same entity, so for now allow the
|
||||
// redeclaration and change the owning modules to match.
|
||||
if (New->getFriendObjectKind() &&
|
||||
Old->getOwningModuleForLinkage() != New->getOwningModuleForLinkage()) {
|
||||
New->setLocalOwningModule(Old->getOwningModule());
|
||||
makeMergedDefinitionVisible(New);
|
||||
return false;
|
||||
}
|
||||
|
||||
Module *NewM = New->getOwningModule();
|
||||
Module *OldM = Old->getOwningModule();
|
||||
if (NewM == OldM)
|
||||
return false;
|
||||
|
||||
// FIXME: Check proclaimed-ownership-declarations here too.
|
||||
bool NewIsModuleInterface = NewM && NewM->Kind == Module::ModuleInterfaceUnit;
|
||||
bool OldIsModuleInterface = OldM && OldM->Kind == Module::ModuleInterfaceUnit;
|
||||
if (NewIsModuleInterface || OldIsModuleInterface) {
|
||||
// C++ Modules TS [basic.def.odr] 6.2/6.7 [sic]:
|
||||
// if a declaration of D [...] appears in the purview of a module, all
|
||||
// other such declarations shall appear in the purview of the same module
|
||||
Diag(New->getLocation(), diag::err_mismatched_owning_module)
|
||||
<< New
|
||||
<< NewIsModuleInterface
|
||||
<< (NewIsModuleInterface ? NewM->getFullModuleName() : "")
|
||||
<< OldIsModuleInterface
|
||||
<< (OldIsModuleInterface ? OldM->getFullModuleName() : "");
|
||||
Diag(Old->getLocation(), diag::note_previous_declaration);
|
||||
New->setInvalidDecl();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isUsingDecl(NamedDecl *D) {
|
||||
return isa<UsingShadowDecl>(D) ||
|
||||
isa<UnresolvedUsingTypenameDecl>(D) ||
|
||||
|
@ -2962,6 +3002,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
|
|||
New->dropAttr<InternalLinkageAttr>();
|
||||
}
|
||||
|
||||
if (CheckRedeclarationModuleOwnership(New, Old))
|
||||
return true;
|
||||
|
||||
if (!getLangOpts().CPlusPlus) {
|
||||
bool OldOvl = Old->hasAttr<OverloadableAttr>();
|
||||
if (OldOvl != New->hasAttr<OverloadableAttr>() && !Old->isImplicit()) {
|
||||
|
@ -3831,6 +3874,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
|||
return New->setInvalidDecl();
|
||||
}
|
||||
|
||||
if (CheckRedeclarationModuleOwnership(New, Old))
|
||||
return;
|
||||
|
||||
// Variables with external linkage are analyzed in FinalizeDeclaratorGroup.
|
||||
|
||||
// FIXME: The test for external storage here seems wrong? We still
|
||||
|
@ -4382,7 +4428,7 @@ static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
|
|||
SourceLocation NameLoc,
|
||||
bool IsUnion) {
|
||||
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName,
|
||||
Sema::ForRedeclaration);
|
||||
Sema::ForVisibleRedeclaration);
|
||||
if (!SemaRef.LookupName(R, S)) return false;
|
||||
|
||||
// Pick a representative declaration.
|
||||
|
@ -5321,7 +5367,7 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
|
|||
D.setInvalidType();
|
||||
|
||||
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
forRedeclarationInCurContext());
|
||||
|
||||
// See if this is a redefinition of a variable in the same scope.
|
||||
if (!D.getCXXScopeSpec().isSet()) {
|
||||
|
@ -5347,8 +5393,10 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
|
|||
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
|
||||
CreateBuiltins = true;
|
||||
|
||||
if (IsLinkageLookup)
|
||||
if (IsLinkageLookup) {
|
||||
Previous.clear(LookupRedeclarationWithLinkage);
|
||||
Previous.setRedeclarationKind(ForExternalRedeclaration);
|
||||
}
|
||||
|
||||
LookupName(Previous, S, CreateBuiltins);
|
||||
} else { // Something like "int foo::x;"
|
||||
|
@ -7096,7 +7144,7 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) {
|
|||
return;
|
||||
|
||||
LookupResult R(*this, D->getDeclName(), D->getLocation(),
|
||||
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
|
||||
Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration);
|
||||
LookupName(R, S);
|
||||
if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R))
|
||||
CheckShadow(D, ShadowedDecl, R);
|
||||
|
@ -7672,7 +7720,7 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
|
|||
LookupResult Prev(SemaRef, Name, NewFD->getLocation(),
|
||||
IsLocalFriend ? Sema::LookupLocalFriendName
|
||||
: Sema::LookupOrdinaryName,
|
||||
Sema::ForRedeclaration);
|
||||
Sema::ForVisibleRedeclaration);
|
||||
|
||||
NewFD->setInvalidDecl();
|
||||
if (IsLocalFriend)
|
||||
|
@ -11708,7 +11756,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
|
|||
// Check for redeclaration of parameters, e.g. int foo(int x, int x);
|
||||
if (II) {
|
||||
LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
ForVisibleRedeclaration);
|
||||
LookupName(R, S);
|
||||
if (R.isSingleResult()) {
|
||||
NamedDecl *PrevDecl = R.getFoundDecl();
|
||||
|
@ -13268,7 +13316,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
bool isStdBadAlloc = false;
|
||||
bool isStdAlignValT = false;
|
||||
|
||||
RedeclarationKind Redecl = ForRedeclaration;
|
||||
RedeclarationKind Redecl = forRedeclarationInCurContext();
|
||||
if (TUK == TUK_Friend || TUK == TUK_Reference)
|
||||
Redecl = NotForRedeclaration;
|
||||
|
||||
|
@ -13546,10 +13594,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
// type declared by an elaborated-type-specifier. In C that is not correct
|
||||
// and we should instead merge compatible types found by lookup.
|
||||
if (getLangOpts().CPlusPlus) {
|
||||
Previous.setRedeclarationKind(ForRedeclaration);
|
||||
Previous.setRedeclarationKind(forRedeclarationInCurContext());
|
||||
LookupQualifiedName(Previous, SearchDC);
|
||||
} else {
|
||||
Previous.setRedeclarationKind(ForRedeclaration);
|
||||
Previous.setRedeclarationKind(forRedeclarationInCurContext());
|
||||
LookupName(Previous, S);
|
||||
}
|
||||
}
|
||||
|
@ -14047,6 +14095,9 @@ CreateNewDecl:
|
|||
if (!Invalid && SearchDC->isRecord())
|
||||
SetMemberAccessSpecifier(New, PrevDecl, AS);
|
||||
|
||||
if (PrevDecl)
|
||||
CheckRedeclarationModuleOwnership(New, PrevDecl);
|
||||
|
||||
if (TUK == TUK_Definition)
|
||||
New->startDefinition();
|
||||
|
||||
|
@ -14400,7 +14451,8 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record,
|
|||
|
||||
// Check to see if this name was declared as a member previously
|
||||
NamedDecl *PrevDecl = nullptr;
|
||||
LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
|
||||
LookupResult Previous(*this, II, Loc, LookupMemberName,
|
||||
ForVisibleRedeclaration);
|
||||
LookupName(Previous, S);
|
||||
switch (Previous.getResultKind()) {
|
||||
case LookupResult::Found:
|
||||
|
@ -14788,7 +14840,7 @@ Decl *Sema::ActOnIvar(Scope *S,
|
|||
|
||||
if (II) {
|
||||
NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName,
|
||||
ForRedeclaration);
|
||||
ForVisibleRedeclaration);
|
||||
if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S)
|
||||
&& !isa<TagDecl>(PrevDecl)) {
|
||||
Diag(Loc, diag::err_duplicate_member) << II;
|
||||
|
@ -15509,7 +15561,7 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II,
|
|||
// determine if we should merge the definition with an existing one and
|
||||
// skip the body.
|
||||
NamedDecl *PrevDecl = LookupSingleName(S, II, IILoc, LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
forRedeclarationInCurContext());
|
||||
auto *PrevECD = dyn_cast_or_null<EnumConstantDecl>(PrevDecl);
|
||||
if (!PrevECD)
|
||||
return SkipBodyInfo();
|
||||
|
@ -15540,7 +15592,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
|
|||
// Verify that there isn't already something declared with this name in this
|
||||
// scope.
|
||||
NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
ForVisibleRedeclaration);
|
||||
if (PrevDecl && PrevDecl->isTemplateParameter()) {
|
||||
// Maybe we will complain about the shadowed template parameter.
|
||||
DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);
|
||||
|
@ -15567,8 +15619,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
|
|||
// enum constant will 'hide' the tag.
|
||||
assert((getLangOpts().CPlusPlus || !isa<TagDecl>(PrevDecl)) &&
|
||||
"Received TagDecl when not in C++!");
|
||||
if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S) &&
|
||||
shouldLinkPossiblyHiddenDecl(PrevDecl, New)) {
|
||||
if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) {
|
||||
if (isa<EnumConstantDecl>(PrevDecl))
|
||||
Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id;
|
||||
else
|
||||
|
@ -16150,7 +16201,8 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
|
|||
else if (const auto *FE = M->getASTFile())
|
||||
Diag(M->DefinitionLoc, diag::note_prev_module_definition_from_ast_file)
|
||||
<< FE->getName();
|
||||
return nullptr;
|
||||
Mod = M;
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a Module for the module that we're defining.
|
||||
|
@ -16169,6 +16221,7 @@ Sema::DeclGroupPtrTy Sema::ActOnModuleDecl(SourceLocation StartLoc,
|
|||
PP.getIdentifierInfo(ModuleName), Path[0].second);
|
||||
Mod = getModuleLoader().loadModule(ModuleLoc, Path, Module::AllVisible,
|
||||
/*IsIncludeDirective=*/false);
|
||||
// FIXME: Produce an error in this case.
|
||||
if (!Mod)
|
||||
return nullptr;
|
||||
break;
|
||||
|
|
|
@ -790,7 +790,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
|
|||
// Check for name conflicts.
|
||||
DeclarationNameInfo NameInfo(B.Name, B.NameLoc);
|
||||
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
ForVisibleRedeclaration);
|
||||
LookupName(Previous, S,
|
||||
/*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit());
|
||||
|
||||
|
@ -822,7 +822,8 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
|
|||
// is unnamed.
|
||||
DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr,
|
||||
Decomp.getLSquareLoc());
|
||||
LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration);
|
||||
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
|
||||
ForVisibleRedeclaration);
|
||||
|
||||
// Build the variable that holds the non-decomposed object.
|
||||
bool AddToScope = true;
|
||||
|
@ -8465,7 +8466,8 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
|
|||
// Since namespace names are unique in their scope, and we don't
|
||||
// look through using directives, just look for any ordinary names
|
||||
// as if by qualified name lookup.
|
||||
LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, ForRedeclaration);
|
||||
LookupResult R(*this, II, IdentLoc, LookupOrdinaryName,
|
||||
ForExternalRedeclaration);
|
||||
LookupQualifiedName(R, CurContext->getRedeclContext());
|
||||
NamedDecl *PrevDecl =
|
||||
R.isSingleResult() ? R.getRepresentativeDecl() : nullptr;
|
||||
|
@ -9402,7 +9404,7 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
|
|||
|
||||
// Do the redeclaration lookup in the current scope.
|
||||
LookupResult Previous(*this, UsingName, LookupUsingDeclName,
|
||||
ForRedeclaration);
|
||||
ForVisibleRedeclaration);
|
||||
Previous.setHideTags(false);
|
||||
if (S) {
|
||||
LookupName(Previous, S);
|
||||
|
@ -9982,7 +9984,10 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
|
|||
TInfo->getTypeLoc().getBeginLoc());
|
||||
}
|
||||
|
||||
LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration);
|
||||
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
|
||||
TemplateParamLists.size()
|
||||
? forRedeclarationInCurContext()
|
||||
: ForVisibleRedeclaration);
|
||||
LookupName(Previous, S);
|
||||
|
||||
// Warn about shadowing the name of a template parameter.
|
||||
|
@ -10085,8 +10090,10 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
|
|||
|
||||
if (Invalid)
|
||||
NewDecl->setInvalidDecl();
|
||||
else if (OldDecl)
|
||||
else if (OldDecl) {
|
||||
NewDecl->setPreviousDecl(OldDecl);
|
||||
CheckRedeclarationModuleOwnership(NewDecl, OldDecl);
|
||||
}
|
||||
|
||||
NewND = NewDecl;
|
||||
} else {
|
||||
|
@ -10127,7 +10134,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
|
|||
|
||||
// Check if we have a previous declaration with the same name.
|
||||
LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
ForVisibleRedeclaration);
|
||||
LookupName(PrevR, S);
|
||||
|
||||
// Check we're not shadowing a template parameter.
|
||||
|
@ -10340,7 +10347,8 @@ void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) {
|
|||
// implicit special members with this name.
|
||||
DeclarationName Name = FD->getDeclName();
|
||||
LookupResult R(*this, Name, SourceLocation(), LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
FD->isExternallyDeclarable() ? ForExternalRedeclaration
|
||||
: ForVisibleRedeclaration);
|
||||
for (auto *D : FD->getParent()->lookup(Name))
|
||||
if (auto *Acceptable = R.getAcceptableDecl(D))
|
||||
R.addDecl(Acceptable);
|
||||
|
@ -13224,7 +13232,7 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
|
|||
IdentifierInfo *II = D.getIdentifier();
|
||||
if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(),
|
||||
LookupOrdinaryName,
|
||||
ForRedeclaration)) {
|
||||
ForVisibleRedeclaration)) {
|
||||
// The scope should be freshly made just for us. There is just no way
|
||||
// it contains any previous declaration, except for function parameters in
|
||||
// a function-try-block's catch statement.
|
||||
|
@ -13673,7 +13681,7 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
|
|||
DeclContext *DC;
|
||||
Scope *DCScope = S;
|
||||
LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
ForExternalRedeclaration);
|
||||
|
||||
// There are five cases here.
|
||||
// - There's no scope specifier and we're in a local class. Only look
|
||||
|
@ -14947,7 +14955,8 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
|
|||
|
||||
// Check to see if this name was declared as a member previously
|
||||
NamedDecl *PrevDecl = nullptr;
|
||||
LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration);
|
||||
LookupResult Previous(*this, II, Loc, LookupMemberName,
|
||||
ForVisibleRedeclaration);
|
||||
LookupName(Previous, S);
|
||||
switch (Previous.getResultKind()) {
|
||||
case LookupResult::Found:
|
||||
|
|
|
@ -943,8 +943,9 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
|
|||
assert(ClassName && "Missing class identifier");
|
||||
|
||||
// Check for another declaration kind with the same name.
|
||||
NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc,
|
||||
LookupOrdinaryName, ForRedeclaration);
|
||||
NamedDecl *PrevDecl =
|
||||
LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
|
||||
forRedeclarationInCurContext());
|
||||
|
||||
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
|
||||
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
|
||||
|
@ -1095,16 +1096,18 @@ Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc,
|
|||
IdentifierInfo *ClassName,
|
||||
SourceLocation ClassLocation) {
|
||||
// Look for previous declaration of alias name
|
||||
NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation,
|
||||
LookupOrdinaryName, ForRedeclaration);
|
||||
NamedDecl *ADecl =
|
||||
LookupSingleName(TUScope, AliasName, AliasLocation, LookupOrdinaryName,
|
||||
forRedeclarationInCurContext());
|
||||
if (ADecl) {
|
||||
Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
|
||||
Diag(ADecl->getLocation(), diag::note_previous_declaration);
|
||||
return nullptr;
|
||||
}
|
||||
// Check for class declaration
|
||||
NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
|
||||
LookupOrdinaryName, ForRedeclaration);
|
||||
NamedDecl *CDeclU =
|
||||
LookupSingleName(TUScope, ClassName, ClassLocation, LookupOrdinaryName,
|
||||
forRedeclarationInCurContext());
|
||||
if (const TypedefNameDecl *TDecl =
|
||||
dyn_cast_or_null<TypedefNameDecl>(CDeclU)) {
|
||||
QualType T = TDecl->getUnderlyingType();
|
||||
|
@ -1112,7 +1115,8 @@ Decl *Sema::ActOnCompatibilityAlias(SourceLocation AtLoc,
|
|||
if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
|
||||
ClassName = IDecl->getIdentifier();
|
||||
CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation,
|
||||
LookupOrdinaryName, ForRedeclaration);
|
||||
LookupOrdinaryName,
|
||||
forRedeclarationInCurContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1174,7 +1178,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
|
|||
// FIXME: Deal with AttrList.
|
||||
assert(ProtocolName && "Missing protocol identifier");
|
||||
ObjCProtocolDecl *PrevDecl = LookupProtocol(ProtocolName, ProtocolLoc,
|
||||
ForRedeclaration);
|
||||
forRedeclarationInCurContext());
|
||||
ObjCProtocolDecl *PDecl = nullptr;
|
||||
if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) {
|
||||
// If we already have a definition, complain.
|
||||
|
@ -1730,7 +1734,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
|
|||
for (const IdentifierLocPair &IdentPair : IdentList) {
|
||||
IdentifierInfo *Ident = IdentPair.first;
|
||||
ObjCProtocolDecl *PrevDecl = LookupProtocol(Ident, IdentPair.second,
|
||||
ForRedeclaration);
|
||||
forRedeclarationInCurContext());
|
||||
ObjCProtocolDecl *PDecl
|
||||
= ObjCProtocolDecl::Create(Context, CurContext, Ident,
|
||||
IdentPair.second, AtProtocolLoc,
|
||||
|
@ -1921,7 +1925,7 @@ Decl *Sema::ActOnStartClassImplementation(
|
|||
// Check for another declaration kind with the same name.
|
||||
NamedDecl *PrevDecl
|
||||
= LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
forRedeclarationInCurContext());
|
||||
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
|
||||
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||
|
@ -2997,7 +3001,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
|
|||
// Check for another declaration kind with the same name.
|
||||
NamedDecl *PrevDecl
|
||||
= LookupSingleName(TUScope, IdentList[i], IdentLocs[i],
|
||||
LookupOrdinaryName, ForRedeclaration);
|
||||
LookupOrdinaryName, forRedeclarationInCurContext());
|
||||
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
|
||||
// GCC apparently allows the following idiom:
|
||||
//
|
||||
|
@ -4443,7 +4447,7 @@ Decl *Sema::ActOnMethodDeclaration(
|
|||
}
|
||||
|
||||
LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc,
|
||||
LookupOrdinaryName, ForRedeclaration);
|
||||
LookupOrdinaryName, forRedeclarationInCurContext());
|
||||
LookupName(R, S);
|
||||
if (R.isSingleResult()) {
|
||||
NamedDecl *PrevDecl = R.getFoundDecl();
|
||||
|
|
|
@ -693,8 +693,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
|
|||
Sema::RedeclarationKind Redecl;
|
||||
};
|
||||
QueryState Q = {R.getSema(), R.getLookupNameInfo(), R.getLookupKind(),
|
||||
R.isForRedeclaration() ? Sema::ForRedeclaration
|
||||
: Sema::NotForRedeclaration};
|
||||
R.redeclarationKind()};
|
||||
TE = SemaRef.CorrectTypoDelayed(
|
||||
R.getLookupNameInfo(), R.getLookupKind(), nullptr, &SS,
|
||||
llvm::make_unique<RecordMemberExprValidatorCCC>(RTy),
|
||||
|
|
|
@ -1609,11 +1609,39 @@ bool Sema::isVisibleSlow(const NamedDecl *D) {
|
|||
}
|
||||
|
||||
bool Sema::shouldLinkPossiblyHiddenDecl(LookupResult &R, const NamedDecl *New) {
|
||||
// FIXME: If there are both visible and hidden declarations, we need to take
|
||||
// into account whether redeclaration is possible. Example:
|
||||
//
|
||||
// Non-imported module:
|
||||
// int f(T); // #1
|
||||
// Some TU:
|
||||
// static int f(U); // #2, not a redeclaration of #1
|
||||
// int f(T); // #3, finds both, should link with #1 if T != U, but
|
||||
// // with #2 if T == U; neither should be ambiguous.
|
||||
for (auto *D : R) {
|
||||
if (isVisible(D))
|
||||
return true;
|
||||
assert(D->isExternallyDeclarable() &&
|
||||
"should not have hidden, non-externally-declarable result here");
|
||||
}
|
||||
return New->isExternallyVisible();
|
||||
|
||||
// This function is called once "New" is essentially complete, but before a
|
||||
// previous declaration is attached. We can't query the linkage of "New" in
|
||||
// general, because attaching the previous declaration can change the
|
||||
// linkage of New to match the previous declaration.
|
||||
//
|
||||
// However, because we've just determined that there is no *visible* prior
|
||||
// declaration, we can compute the linkage here. There are two possibilities:
|
||||
//
|
||||
// * This is not a redeclaration; it's safe to compute the linkage now.
|
||||
//
|
||||
// * This is a redeclaration of a prior declaration that is externally
|
||||
// redeclarable. In that case, the linkage of the declaration is not
|
||||
// changed by attaching the prior declaration, because both are externally
|
||||
// declarable (and thus ExternalLinkage or VisibleNoLinkage).
|
||||
//
|
||||
// FIXME: This is subtle and fragile.
|
||||
return New->isExternallyDeclarable();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the visible declaration corresponding to D, if any.
|
||||
|
|
|
@ -11539,7 +11539,7 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareReductionDirectiveStart(
|
|||
Decls.reserve(ReductionTypes.size());
|
||||
|
||||
LookupResult Lookup(*this, Name, SourceLocation(), LookupOMPReductionName,
|
||||
ForRedeclaration);
|
||||
forRedeclarationInCurContext());
|
||||
// [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
|
||||
// A reduction-identifier may not be re-declared in the current scope for the
|
||||
// same type or for a type that is compatible according to the base language
|
||||
|
|
|
@ -778,7 +778,7 @@ static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
|
|||
SourceLocation Loc,
|
||||
IdentifierInfo *Name) {
|
||||
NamedDecl *PrevDecl = SemaRef.LookupSingleName(
|
||||
S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForRedeclaration);
|
||||
S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration);
|
||||
if (PrevDecl && PrevDecl->isTemplateParameter())
|
||||
SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl);
|
||||
}
|
||||
|
@ -1133,7 +1133,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
LookupResult Previous(*this, Name, NameLoc,
|
||||
(SS.isEmpty() && TUK == TUK_Friend)
|
||||
? LookupTagName : LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
forRedeclarationInCurContext());
|
||||
if (SS.isNotEmpty() && !SS.isInvalid()) {
|
||||
SemanticContext = computeDeclContext(SS, true);
|
||||
if (!SemanticContext) {
|
||||
|
@ -1192,8 +1192,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
|
||||
// If there is a previous declaration with the same name, check
|
||||
// whether this is a valid redeclaration.
|
||||
ClassTemplateDecl *PrevClassTemplate
|
||||
= dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
|
||||
ClassTemplateDecl *PrevClassTemplate =
|
||||
dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
|
||||
|
||||
// We may have found the injected-class-name of a class template,
|
||||
// class template partial specialization, or class template specialization.
|
||||
|
@ -1484,6 +1484,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
|||
CurContext->addDecl(Friend);
|
||||
}
|
||||
|
||||
if (PrevClassTemplate)
|
||||
CheckRedeclarationModuleOwnership(NewTemplate, PrevClassTemplate);
|
||||
|
||||
if (Invalid) {
|
||||
NewTemplate->setInvalidDecl();
|
||||
NewClass->setInvalidDecl();
|
||||
|
@ -3677,7 +3680,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
|
|||
// Check that this isn't a redefinition of this specialization,
|
||||
// merging with previous declarations.
|
||||
LookupResult PrevSpec(*this, GetNameForDeclarator(D), LookupOrdinaryName,
|
||||
ForRedeclaration);
|
||||
forRedeclarationInCurContext());
|
||||
PrevSpec.addDecl(PrevDecl);
|
||||
D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec));
|
||||
} else if (Specialization->isStaticDataMember() &&
|
||||
|
|
|
@ -1195,7 +1195,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
|||
// Look for a previous declaration of the template in the owning
|
||||
// context.
|
||||
LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(),
|
||||
Sema::LookupOrdinaryName, Sema::ForRedeclaration);
|
||||
Sema::LookupOrdinaryName,
|
||||
SemaRef.forRedeclarationInCurContext());
|
||||
SemaRef.LookupQualifiedName(R, DC);
|
||||
|
||||
if (R.isSingleResult()) {
|
||||
|
@ -1735,7 +1736,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
|
|||
SemaRef, Function->getDeclName(), SourceLocation(),
|
||||
D->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
|
||||
: Sema::LookupOrdinaryName,
|
||||
Sema::ForRedeclaration);
|
||||
D->isLocalExternDecl() ? Sema::ForExternalRedeclaration
|
||||
: SemaRef.forRedeclarationInCurContext());
|
||||
|
||||
if (DependentFunctionTemplateSpecializationInfo *Info
|
||||
= D->getDependentSpecializationInfo()) {
|
||||
|
@ -2053,7 +2055,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
|||
Method->setInvalidDecl();
|
||||
|
||||
LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
|
||||
Sema::ForRedeclaration);
|
||||
Sema::ForExternalRedeclaration);
|
||||
|
||||
if (!FunctionTemplate || TemplateParams || isFriend) {
|
||||
SemaRef.LookupQualifiedName(Previous, Record);
|
||||
|
@ -2492,7 +2494,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
|
|||
bool CheckRedeclaration = Owner->isRecord();
|
||||
|
||||
LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName,
|
||||
Sema::ForRedeclaration);
|
||||
Sema::ForVisibleRedeclaration);
|
||||
|
||||
UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
|
||||
D->getUsingLoc(),
|
||||
|
@ -2711,7 +2713,7 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
|
|||
return nullptr;
|
||||
|
||||
LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
|
||||
Sema::ForRedeclaration);
|
||||
Sema::ForExternalRedeclaration);
|
||||
|
||||
TemplateArgumentListInfo TemplateArgs;
|
||||
TemplateArgumentListInfo *TemplateArgsPtr = nullptr;
|
||||
|
@ -4074,7 +4076,8 @@ void Sema::BuildVariableInstantiation(
|
|||
*this, NewVar->getDeclName(), NewVar->getLocation(),
|
||||
NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
|
||||
: Sema::LookupOrdinaryName,
|
||||
Sema::ForRedeclaration);
|
||||
NewVar->isLocalExternDecl() ? Sema::ForExternalRedeclaration
|
||||
: forRedeclarationInCurContext());
|
||||
|
||||
if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl() &&
|
||||
(!OldVar->getPreviousDecl()->getDeclContext()->isDependentContext() ||
|
||||
|
@ -4432,7 +4435,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
|||
|
||||
// Merge the definition with the declaration.
|
||||
LookupResult R(*this, Var->getDeclName(), Var->getLocation(),
|
||||
LookupOrdinaryName, ForRedeclaration);
|
||||
LookupOrdinaryName, forRedeclarationInCurContext());
|
||||
R.addDecl(OldVar);
|
||||
MergeVarDecl(Var, R);
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// RUN: %clang_cc1 -fmodules-ts -verify -std=c++17 %s
|
||||
// RUN: %clang_cc1 -fmodules-ts -verify -std=c++17 %s -DEXPORT
|
||||
// RUN: %clang_cc1 -fmodules-ts -verify -std=c++17 %s -DUSING
|
||||
|
||||
#ifndef NO_GLOBAL
|
||||
extern int var; // expected-note {{previous declaration is here}}
|
||||
int func(); // expected-note {{previous declaration is here}}
|
||||
struct str; // expected-note {{previous declaration is here}}
|
||||
using type = int;
|
||||
|
||||
template<typename> extern int var_tpl; // expected-note {{previous declaration is here}}
|
||||
template<typename> int func_tpl(); // expected-note-re {{{{previous declaration is here|target of using declaration}}}}
|
||||
template<typename> struct str_tpl; // expected-note {{previous declaration is here}}
|
||||
template<typename> using type_tpl = int; // expected-note {{previous declaration is here}}
|
||||
|
||||
typedef int type;
|
||||
namespace ns { using ::func; }
|
||||
namespace ns_alias = ns;
|
||||
#endif
|
||||
|
||||
export module M;
|
||||
|
||||
#ifdef USING
|
||||
using ::var;
|
||||
using ::func;
|
||||
using ::str;
|
||||
using ::type;
|
||||
using ::var_tpl;
|
||||
using ::func_tpl; // expected-note {{using declaration}}
|
||||
using ::str_tpl;
|
||||
using ::type_tpl;
|
||||
#endif
|
||||
|
||||
#ifdef EXPORT
|
||||
export {
|
||||
#endif
|
||||
|
||||
extern int var; // expected-error {{declaration of 'var' in module M follows declaration in the global module}}
|
||||
int func(); // expected-error {{declaration of 'func' in module M follows declaration in the global module}}
|
||||
struct str; // expected-error {{declaration of 'str' in module M follows declaration in the global module}}
|
||||
using type = int;
|
||||
|
||||
template<typename> extern int var_tpl; // expected-error {{declaration of 'var_tpl' in module M follows declaration in the global module}}
|
||||
// FIXME: Is this the right diagnostic in the -DUSING case?
|
||||
template<typename> int func_tpl(); // expected-error-re {{{{declaration of 'func_tpl' in module M follows declaration in the global module|conflicts with target of using declaration}}}}
|
||||
template<typename> struct str_tpl; // expected-error {{declaration of 'str_tpl' in module M follows declaration in the global module}}
|
||||
template<typename> using type_tpl = int; // expected-error {{declaration of 'type_tpl' in module M follows declaration in the global module}}
|
||||
|
||||
typedef int type;
|
||||
namespace ns { using ::func; }
|
||||
namespace ns_alias = ns;
|
||||
|
||||
#ifdef EXPORT
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: %clang_cc1 -fmodules-ts -emit-module-interface -std=c++17 %S/global-vs-module.cpp -o %t -DNO_GLOBAL -DEXPORT
|
||||
// RUN: %clang_cc1 -fmodules-ts -verify -std=c++17 %s -fmodule-file=%t
|
||||
|
||||
import M;
|
||||
|
||||
extern int var; // expected-error {{declaration of 'var' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:38 {{previous}}
|
||||
int func(); // expected-error {{declaration of 'func' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:39 {{previous}}
|
||||
struct str; // expected-error {{declaration of 'str' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:40 {{previous}}
|
||||
using type = int;
|
||||
|
||||
template<typename> extern int var_tpl; // expected-error {{declaration of 'var_tpl' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:43 {{previous}}
|
||||
template<typename> int func_tpl(); // expected-error {{declaration of 'func_tpl' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:45 {{previous}}
|
||||
template<typename> struct str_tpl; // expected-error {{declaration of 'str_tpl' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:46 {{previous}}
|
||||
template<typename> using type_tpl = int; // expected-error {{declaration of 'type_tpl' in the global module follows declaration in module M}} expected-note@global-vs-module.cpp:47 {{previous}}
|
||||
|
||||
typedef int type;
|
||||
namespace ns { using ::func; }
|
||||
namespace ns_alias = ns;
|
|
@ -0,0 +1,44 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: mkdir %t
|
||||
//
|
||||
// Some of the following tests intentionally have no -verify in their RUN
|
||||
// lines; we are testing that those cases do not produce errors.
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules-ts -std=c++17 %S/global-vs-module.cpp -emit-module-interface -o %t/M.pcm -DNO_GLOBAL -DEXPORT
|
||||
// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/M.pcm -DMODULE_INTERFACE -verify
|
||||
// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/M.pcm -DMODULE_INTERFACE -DNO_IMPORT
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/M.pcm -emit-module-interface -o %t/N.pcm -DMODULE_INTERFACE -DNO_ERRORS
|
||||
// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N.pcm -verify
|
||||
// FIXME: Once we start importing "import" declarations properly, this should
|
||||
// be rejected (-verify should be added to the following line).
|
||||
// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N.pcm -DNO_IMPORT
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/M.pcm -emit-module-interface -o %t/N-no-M.pcm -DMODULE_INTERFACE -DNO_ERRORS -DNO_IMPORT
|
||||
// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N-no-M.pcm -verify
|
||||
// RUN: %clang_cc1 -fmodules-ts -std=c++17 %s -fmodule-file=%t/N-no-M.pcm -DNO_IMPORT
|
||||
|
||||
#ifdef MODULE_INTERFACE
|
||||
export
|
||||
#endif
|
||||
module N;
|
||||
|
||||
#ifndef NO_IMPORT
|
||||
import M;
|
||||
#endif
|
||||
|
||||
#ifndef NO_ERRORS
|
||||
extern int var; // expected-error {{declaration of 'var' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:38 {{previous}}
|
||||
int func(); // expected-error {{declaration of 'func' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:39 {{previous}}
|
||||
struct str; // expected-error {{declaration of 'str' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:40 {{previous}}
|
||||
using type = int;
|
||||
|
||||
template<typename> extern int var_tpl; // expected-error {{declaration of 'var_tpl' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:43 {{previous}}
|
||||
template<typename> int func_tpl(); // expected-error {{declaration of 'func_tpl' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:45 {{previous}}
|
||||
template<typename> struct str_tpl; // expected-error {{declaration of 'str_tpl' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:46 {{previous}}
|
||||
template<typename> using type_tpl = int; // expected-error {{declaration of 'type_tpl' in module N follows declaration in module M}} expected-note@global-vs-module.cpp:47 {{previous}}
|
||||
|
||||
typedef int type;
|
||||
namespace ns { using ::func; }
|
||||
namespace ns_alias = ns;
|
||||
#endif
|
|
@ -14,7 +14,7 @@ export module foo;
|
|||
#endif
|
||||
|
||||
static int m;
|
||||
#if TEST == 2 // FIXME: 'm' has internal linkage, so there should be no error here
|
||||
#if TEST == 2
|
||||
// expected-error@-2 {{redefinition of '}}
|
||||
// expected-note@-3 {{unguarded header; consider using #ifdef guards or #pragma once}}
|
||||
// FIXME: We should drop the "header from" in this diagnostic.
|
||||
|
|
Loading…
Reference in New Issue