forked from OSchip/llvm-project
Revert r185229 as it breaks compilation of <windows.h>
llvm-svn: 185256
This commit is contained in:
parent
243e53977a
commit
32d1e73023
|
@ -3493,11 +3493,6 @@ def err_static_non_static : Error<
|
||||||
"static declaration of %0 follows non-static declaration">;
|
"static declaration of %0 follows non-static declaration">;
|
||||||
def err_different_language_linkage : Error<
|
def err_different_language_linkage : Error<
|
||||||
"declaration of %0 has a different language linkage">;
|
"declaration of %0 has a different language linkage">;
|
||||||
def err_extern_c_global_conflict : Error<
|
|
||||||
"declaration of %1 %select{with C language linkage|in global scope}0 "
|
|
||||||
"conflicts with declaration %select{in global scope|with C language linkage}0">;
|
|
||||||
def note_extern_c_global_conflict : Note<
|
|
||||||
"declared %select{in global scope|with C language linkage}0 here">;
|
|
||||||
def warn_weak_import : Warning <
|
def warn_weak_import : Warning <
|
||||||
"an already-declared variable is made a weak_import declaration %0">;
|
"an already-declared variable is made a weak_import declaration %0">;
|
||||||
def warn_static_non_static : ExtWarn<
|
def warn_static_non_static : ExtWarn<
|
||||||
|
|
|
@ -4359,14 +4359,10 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo,
|
||||||
/// function-scope declarations.
|
/// function-scope declarations.
|
||||||
void
|
void
|
||||||
Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) {
|
Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) {
|
||||||
if (!getLangOpts().CPlusPlus &&
|
assert(
|
||||||
ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit())
|
!ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit() &&
|
||||||
// Don't need to track declarations in the TU in C.
|
"Decl is not a locally-scoped decl!");
|
||||||
return;
|
|
||||||
|
|
||||||
// Note that we have a locally-scoped external with this name.
|
// Note that we have a locally-scoped external with this name.
|
||||||
// FIXME: There can be multiple such declarations if they are functions marked
|
|
||||||
// __attribute__((overloadable)) declared in function scope in C.
|
|
||||||
LocallyScopedExternCDecls[ND->getDeclName()] = ND;
|
LocallyScopedExternCDecls[ND->getDeclName()] = ND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4685,32 +4681,6 @@ static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) {
|
||||||
return isC99Inline;
|
return isC99Inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether a variable is extern "C" prior to attaching
|
|
||||||
/// an initializer. We can't just call isExternC() here, because that
|
|
||||||
/// will also compute and cache whether the declaration is externally
|
|
||||||
/// visible, which might change when we attach the initializer.
|
|
||||||
///
|
|
||||||
/// This can only be used if the declaration is known to not be a
|
|
||||||
/// redeclaration of an internal linkage declaration.
|
|
||||||
///
|
|
||||||
/// For instance:
|
|
||||||
///
|
|
||||||
/// auto x = []{};
|
|
||||||
///
|
|
||||||
/// Attaching the initializer here makes this declaration not externally
|
|
||||||
/// visible, because its type has internal linkage.
|
|
||||||
///
|
|
||||||
/// FIXME: This is a hack.
|
|
||||||
template<typename T>
|
|
||||||
static bool isIncompleteDeclExternC(Sema &S, const T *D) {
|
|
||||||
if (S.getLangOpts().CPlusPlus) {
|
|
||||||
// In C++, the overloadable attribute negates the effects of extern "C".
|
|
||||||
if (!D->isInExternCContext() || D->template hasAttr<OverloadableAttr>())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return D->isExternC();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool shouldConsiderLinkage(const VarDecl *VD) {
|
static bool shouldConsiderLinkage(const VarDecl *VD) {
|
||||||
const DeclContext *DC = VD->getDeclContext()->getRedeclContext();
|
const DeclContext *DC = VD->getDeclContext()->getRedeclContext();
|
||||||
if (DC->isFunctionOrMethod())
|
if (DC->isFunctionOrMethod())
|
||||||
|
@ -5100,10 +5070,16 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||||
ProcessPragmaWeak(S, NewVD);
|
ProcessPragmaWeak(S, NewVD);
|
||||||
checkAttributesAfterMerging(*this, *NewVD);
|
checkAttributesAfterMerging(*this, *NewVD);
|
||||||
|
|
||||||
// If this is the first declaration of an extern C variable, update
|
// If this is the first declaration of an extern C variable that is not
|
||||||
// the map of such variables.
|
// declared directly in the translation unit, update the map of such
|
||||||
if (!NewVD->getPreviousDecl() && !NewVD->isInvalidDecl() &&
|
// variables.
|
||||||
isIncompleteDeclExternC(*this, NewVD))
|
if (!CurContext->getRedeclContext()->isTranslationUnit() &&
|
||||||
|
!NewVD->getPreviousDecl() && !NewVD->isInvalidDecl() &&
|
||||||
|
// FIXME: We only check isExternC if we're in an extern C context,
|
||||||
|
// to avoid computing and caching an 'externally visible' flag which
|
||||||
|
// could change if the variable's type is not visible.
|
||||||
|
(!getLangOpts().CPlusPlus || NewVD->isInExternCContext()) &&
|
||||||
|
NewVD->isExternC())
|
||||||
RegisterLocallyScopedExternCDecl(NewVD, S);
|
RegisterLocallyScopedExternCDecl(NewVD, S);
|
||||||
|
|
||||||
return NewVD;
|
return NewVD;
|
||||||
|
@ -5204,120 +5180,30 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) {
|
||||||
CheckShadow(S, D, R);
|
CheckShadow(S, D, R);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check for conflict between this global or extern "C" declaration and
|
|
||||||
/// previous global or extern "C" declarations. This is only used in C++.
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static bool checkGlobalOrExternCConflict(
|
static bool mayConflictWithNonVisibleExternC(const T *ND) {
|
||||||
Sema &S, const T *ND, bool IsGlobal, LookupResult &Previous) {
|
const DeclContext *DC = ND->getDeclContext();
|
||||||
assert(S.getLangOpts().CPlusPlus && "only C++ has extern \"C\"");
|
if (DC->getRedeclContext()->isTranslationUnit())
|
||||||
NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName());
|
|
||||||
|
|
||||||
if (!Prev && IsGlobal && !isIncompleteDeclExternC(S, ND)) {
|
|
||||||
// The common case: this global doesn't conflict with any extern "C"
|
|
||||||
// declaration.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Prev) {
|
|
||||||
if (!IsGlobal || isIncompleteDeclExternC(S, ND)) {
|
|
||||||
// Both the old and new declarations have C language linkage. This is a
|
|
||||||
// redeclaration.
|
|
||||||
Previous.clear();
|
|
||||||
Previous.addDecl(Prev);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
// This is a global, non-extern "C" declaration, and there is a previous
|
// We know that is the first decl we see, other than function local
|
||||||
// non-global extern "C" declaration. Diagnose.
|
// extern C ones. If this is C++ and the decl is not in a extern C context
|
||||||
} else {
|
// it cannot have C language linkage. Avoid calling isExternC in that case.
|
||||||
// The declaration is extern "C". Check for any declaration in the
|
// We need to this because of code like
|
||||||
// translation unit which might conflict.
|
|
||||||
if (IsGlobal) {
|
|
||||||
// We have already performed the lookup into the translation unit.
|
|
||||||
IsGlobal = false;
|
|
||||||
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
if (isa<VarDecl>(*I) || isa<FunctionDecl>(*I)) {
|
|
||||||
Prev = *I;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DeclContext::lookup_result R =
|
|
||||||
S.Context.getTranslationUnitDecl()->lookup(ND->getDeclName());
|
|
||||||
for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
if (isa<VarDecl>(*I) || isa<FunctionDecl>(*I)) {
|
|
||||||
Prev = *I;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// FIXME: If we have any other entity with this name in global scope,
|
|
||||||
// the declaration is ill-formed, but that is a defect: it breaks the
|
|
||||||
// 'stat' hack, for instance.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Prev)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the first declaration's location to ensure we point at something which
|
|
||||||
// is lexically inside an extern "C" linkage-spec.
|
|
||||||
assert(Prev && "should have found a previous declaration to diagnose");
|
|
||||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Prev))
|
|
||||||
Prev = FD->getFirstDeclaration();
|
|
||||||
else
|
|
||||||
Prev = cast<VarDecl>(Prev)->getFirstDeclaration();
|
|
||||||
|
|
||||||
S.Diag(ND->getLocation(), diag::err_extern_c_global_conflict)
|
|
||||||
<< IsGlobal << ND;
|
|
||||||
S.Diag(Prev->getLocation(), diag::note_extern_c_global_conflict)
|
|
||||||
<< IsGlobal;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Apply special rules for handling extern "C" declarations. Returns \c true
|
|
||||||
/// if we have found that this is a redeclaration of some prior entity.
|
|
||||||
///
|
|
||||||
/// Per C++ [dcl.link]p6:
|
|
||||||
/// Two declarations [for a function or variable] with C language linkage
|
|
||||||
/// with the same name that appear in different scopes refer to the same
|
|
||||||
/// [entity]. An entity with C language linkage shall not be declared with
|
|
||||||
/// the same name as an entity in global scope.
|
|
||||||
template<typename T>
|
|
||||||
static bool checkForConflictWithNonVisibleExternC(Sema &S, const T *ND,
|
|
||||||
LookupResult &Previous) {
|
|
||||||
if (!S.getLangOpts().CPlusPlus) {
|
|
||||||
// In C, when declaring a global variable, look for a corresponding 'extern'
|
|
||||||
// variable declared in function scope.
|
|
||||||
//
|
//
|
||||||
// FIXME: The corresponding case in C++ does not work. We should instead
|
// namespace { struct bar {}; }
|
||||||
// set the semantic DC for an extern local variable to be the innermost
|
// auto foo = bar();
|
||||||
// enclosing namespace, and ensure they are only found by redeclaration
|
//
|
||||||
// lookup.
|
// This code runs before the init of foo is set, and therefore before
|
||||||
if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
|
// the type of foo is known. Not knowing the type we cannot know its linkage
|
||||||
if (NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName())) {
|
// unless it is in an extern C block.
|
||||||
Previous.clear();
|
if (!ND->isInExternCContext()) {
|
||||||
Previous.addDecl(Prev);
|
const ASTContext &Context = ND->getASTContext();
|
||||||
return true;
|
if (Context.getLangOpts().CPlusPlus)
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A declaration in the translation unit can conflict with an extern "C"
|
return ND->isExternC();
|
||||||
// declaration.
|
|
||||||
if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit())
|
|
||||||
return checkGlobalOrExternCConflict(S, ND, /*IsGlobal*/true, Previous);
|
|
||||||
|
|
||||||
// An extern "C" declaration can conflict with a declaration in the
|
|
||||||
// translation unit or can be a redeclaration of an extern "C" declaration
|
|
||||||
// in another scope.
|
|
||||||
if (isIncompleteDeclExternC(S,ND))
|
|
||||||
return checkGlobalOrExternCConflict(S, ND, /*IsGlobal*/false, Previous);
|
|
||||||
|
|
||||||
// Neither global nor extern "C": nothing to do.
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
|
void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
|
||||||
|
@ -5500,9 +5386,14 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD,
|
||||||
// The most important point here is that we're not allowed to
|
// The most important point here is that we're not allowed to
|
||||||
// update our understanding of the type according to declarations
|
// update our understanding of the type according to declarations
|
||||||
// not in scope.
|
// not in scope.
|
||||||
bool PreviousWasHidden =
|
bool PreviousWasHidden = false;
|
||||||
Previous.empty() &&
|
if (Previous.empty() && mayConflictWithNonVisibleExternC(NewVD)) {
|
||||||
checkForConflictWithNonVisibleExternC(*this, NewVD, Previous);
|
if (NamedDecl *ExternCPrev =
|
||||||
|
findLocallyScopedExternCDecl(NewVD->getDeclName())) {
|
||||||
|
Previous.addDecl(ExternCPrev);
|
||||||
|
PreviousWasHidden = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Filter out any non-conflicting previous declarations.
|
// Filter out any non-conflicting previous declarations.
|
||||||
filterNonConflictingPreviousDecls(Context, NewVD, Previous);
|
filterNonConflictingPreviousDecls(Context, NewVD, Previous);
|
||||||
|
@ -6734,10 +6625,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||||
// marking the function.
|
// marking the function.
|
||||||
AddCFAuditedAttribute(NewFD);
|
AddCFAuditedAttribute(NewFD);
|
||||||
|
|
||||||
// If this is the first declaration of an extern C variable, update
|
// If this is the first declaration of an extern C variable that is not
|
||||||
// the map of such variables.
|
// declared directly in the translation unit, update the map of such
|
||||||
if (!NewFD->getPreviousDecl() && !NewFD->isInvalidDecl() &&
|
// variables.
|
||||||
isIncompleteDeclExternC(*this, NewFD))
|
if (!CurContext->getRedeclContext()->isTranslationUnit() &&
|
||||||
|
!NewFD->getPreviousDecl() && NewFD->isExternC() &&
|
||||||
|
!NewFD->isInvalidDecl())
|
||||||
RegisterLocallyScopedExternCDecl(NewFD, S);
|
RegisterLocallyScopedExternCDecl(NewFD, S);
|
||||||
|
|
||||||
// Set this FunctionDecl's range up to the right paren.
|
// Set this FunctionDecl's range up to the right paren.
|
||||||
|
@ -6841,6 +6734,15 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||||
assert(!NewFD->getResultType()->isVariablyModifiedType()
|
assert(!NewFD->getResultType()->isVariablyModifiedType()
|
||||||
&& "Variably modified return types are not handled here");
|
&& "Variably modified return types are not handled here");
|
||||||
|
|
||||||
|
// Check for a previous declaration of this name.
|
||||||
|
if (Previous.empty() && mayConflictWithNonVisibleExternC(NewFD)) {
|
||||||
|
// Since we did not find anything by this name, look for a non-visible
|
||||||
|
// extern "C" declaration with the same name.
|
||||||
|
if (NamedDecl *ExternCPrev =
|
||||||
|
findLocallyScopedExternCDecl(NewFD->getDeclName()))
|
||||||
|
Previous.addDecl(ExternCPrev);
|
||||||
|
}
|
||||||
|
|
||||||
// Filter out any non-conflicting previous declarations.
|
// Filter out any non-conflicting previous declarations.
|
||||||
filterNonConflictingPreviousDecls(Context, NewFD, Previous);
|
filterNonConflictingPreviousDecls(Context, NewFD, Previous);
|
||||||
|
|
||||||
|
@ -6895,34 +6797,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a previous extern "C" declaration with this name.
|
|
||||||
if (!Redeclaration &&
|
|
||||||
checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) {
|
|
||||||
filterNonConflictingPreviousDecls(Context, NewFD, Previous);
|
|
||||||
if (!Previous.empty()) {
|
|
||||||
// This is an extern "C" declaration with the same name as a previous
|
|
||||||
// declaration, and thus redeclares that entity...
|
|
||||||
Redeclaration = true;
|
|
||||||
OldDecl = Previous.getFoundDecl();
|
|
||||||
|
|
||||||
// ... except in the presence of __attribute__((overloadable)).
|
|
||||||
if (OldDecl->hasAttr<OverloadableAttr>()) {
|
|
||||||
if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) {
|
|
||||||
Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
|
|
||||||
<< Redeclaration << NewFD;
|
|
||||||
Diag(Previous.getFoundDecl()->getLocation(),
|
|
||||||
diag::note_attribute_overloadable_prev_overload);
|
|
||||||
NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),
|
|
||||||
Context));
|
|
||||||
}
|
|
||||||
if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) {
|
|
||||||
Redeclaration = false;
|
|
||||||
OldDecl = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// C++11 [dcl.constexpr]p8:
|
// C++11 [dcl.constexpr]p8:
|
||||||
// A constexpr specifier for a non-static member function that is not
|
// A constexpr specifier for a non-static member function that is not
|
||||||
// a constructor declares that member function to be const.
|
// a constructor declares that member function to be const.
|
||||||
|
|
|
@ -977,12 +977,21 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
|
||||||
return Ovl_Overload;
|
return Ovl_Overload;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
|
static bool canBeOverloaded(const FunctionDecl &D) {
|
||||||
bool UseUsingDeclRules) {
|
if (D.getAttr<OverloadableAttr>())
|
||||||
// C++ [basic.start.main]p2: This function shall not be overloaded.
|
return true;
|
||||||
if (New->isMain())
|
if (D.isExternC())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Main cannot be overloaded (basic.start.main).
|
||||||
|
if (D.isMain())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
|
||||||
|
bool UseUsingDeclRules) {
|
||||||
FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
|
FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
|
||||||
FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
|
FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
|
||||||
|
|
||||||
|
@ -993,8 +1002,8 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Is the function New an overload of the function Old?
|
// Is the function New an overload of the function Old?
|
||||||
QualType OldQType = Context.getCanonicalType(Old->getType());
|
QualType OldQType = S.Context.getCanonicalType(Old->getType());
|
||||||
QualType NewQType = Context.getCanonicalType(New->getType());
|
QualType NewQType = S.Context.getCanonicalType(New->getType());
|
||||||
|
|
||||||
// Compare the signatures (C++ 1.3.10) of the two functions to
|
// Compare the signatures (C++ 1.3.10) of the two functions to
|
||||||
// determine whether they are overloads. If we find any mismatch
|
// determine whether they are overloads. If we find any mismatch
|
||||||
|
@ -1015,7 +1024,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
|
||||||
if (OldQType != NewQType &&
|
if (OldQType != NewQType &&
|
||||||
(OldType->getNumArgs() != NewType->getNumArgs() ||
|
(OldType->getNumArgs() != NewType->getNumArgs() ||
|
||||||
OldType->isVariadic() != NewType->isVariadic() ||
|
OldType->isVariadic() != NewType->isVariadic() ||
|
||||||
!FunctionArgTypesAreEqual(OldType, NewType)))
|
!S.FunctionArgTypesAreEqual(OldType, NewType)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// C++ [temp.over.link]p4:
|
// C++ [temp.over.link]p4:
|
||||||
|
@ -1031,9 +1040,9 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
|
||||||
// However, we don't consider either of these when deciding whether
|
// However, we don't consider either of these when deciding whether
|
||||||
// a member introduced by a shadow declaration is hidden.
|
// a member introduced by a shadow declaration is hidden.
|
||||||
if (!UseUsingDeclRules && NewTemplate &&
|
if (!UseUsingDeclRules && NewTemplate &&
|
||||||
(!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
|
(!S.TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
|
||||||
OldTemplate->getTemplateParameters(),
|
OldTemplate->getTemplateParameters(),
|
||||||
false, TPL_TemplateMatch) ||
|
false, S.TPL_TemplateMatch) ||
|
||||||
OldType->getResultType() != NewType->getResultType()))
|
OldType->getResultType() != NewType->getResultType()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -1059,9 +1068,9 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
|
||||||
// declarations with the same name, the same parameter-type-list, and
|
// declarations with the same name, the same parameter-type-list, and
|
||||||
// the same template parameter lists cannot be overloaded if any of
|
// the same template parameter lists cannot be overloaded if any of
|
||||||
// them, but not all, have a ref-qualifier (8.3.5).
|
// them, but not all, have a ref-qualifier (8.3.5).
|
||||||
Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
|
S.Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
|
||||||
<< NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
|
<< NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
|
||||||
Diag(OldMethod->getLocation(), diag::note_previous_declaration);
|
S.Diag(OldMethod->getLocation(), diag::note_previous_declaration);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1071,7 +1080,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
|
||||||
// or non-static member function). Add it now, on the assumption that this
|
// or non-static member function). Add it now, on the assumption that this
|
||||||
// is a redeclaration of OldMethod.
|
// is a redeclaration of OldMethod.
|
||||||
unsigned NewQuals = NewMethod->getTypeQualifiers();
|
unsigned NewQuals = NewMethod->getTypeQualifiers();
|
||||||
if (!getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() &&
|
if (!S.getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() &&
|
||||||
!isa<CXXConstructorDecl>(NewMethod))
|
!isa<CXXConstructorDecl>(NewMethod))
|
||||||
NewQuals |= Qualifiers::Const;
|
NewQuals |= Qualifiers::Const;
|
||||||
if (OldMethod->getTypeQualifiers() != NewQuals)
|
if (OldMethod->getTypeQualifiers() != NewQuals)
|
||||||
|
@ -1082,6 +1091,19 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
|
||||||
|
bool UseUsingDeclRules) {
|
||||||
|
if (!shouldTryToOverload(*this, New, Old, UseUsingDeclRules))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If both of the functions are extern "C", then they are not
|
||||||
|
// overloads.
|
||||||
|
if (!canBeOverloaded(*Old) && !canBeOverloaded(*New))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Checks availability of the function depending on the current
|
/// \brief Checks availability of the function depending on the current
|
||||||
/// function context. Inside an unavailable function, unavailability is ignored.
|
/// function context. Inside an unavailable function, unavailability is ignored.
|
||||||
///
|
///
|
||||||
|
|
|
@ -287,22 +287,22 @@ namespace test9 {
|
||||||
|
|
||||||
// PR7230
|
// PR7230
|
||||||
namespace test10 {
|
namespace test10 {
|
||||||
extern "C" void test10_f(void);
|
extern "C" void f(void);
|
||||||
extern "C" void test10_g(void);
|
extern "C" void g(void);
|
||||||
|
|
||||||
namespace NS {
|
namespace NS {
|
||||||
class C {
|
class C {
|
||||||
void foo(void); // expected-note {{declared private here}}
|
void foo(void); // expected-note {{declared private here}}
|
||||||
friend void test10::test10_f(void);
|
friend void test10::f(void);
|
||||||
};
|
};
|
||||||
static C* bar;
|
static C* bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
void test10_f(void) {
|
void f(void) {
|
||||||
NS::bar->foo();
|
NS::bar->foo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void test10_g(void) {
|
void g(void) {
|
||||||
NS::bar->foo(); // expected-error {{private member}}
|
NS::bar->foo(); // expected-error {{private member}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,18 +69,3 @@ void test() {
|
||||||
f0();
|
f0();
|
||||||
f1();
|
f1();
|
||||||
}
|
}
|
||||||
|
|
||||||
void before_local_1(int) __attribute__((overloadable)); // expected-note {{here}}
|
|
||||||
void before_local_2(int); // expected-note {{here}}
|
|
||||||
void before_local_3(int) __attribute__((overloadable));
|
|
||||||
void local() {
|
|
||||||
void before_local_1(char); // expected-error {{must have the 'overloadable' attribute}}
|
|
||||||
void before_local_2(char) __attribute__((overloadable)); // expected-error {{conflicting types}}
|
|
||||||
void before_local_3(char) __attribute__((overloadable));
|
|
||||||
void after_local_1(char); // expected-note {{here}}
|
|
||||||
void after_local_2(char) __attribute__((overloadable)); // expected-note {{here}}
|
|
||||||
void after_local_3(char) __attribute__((overloadable));
|
|
||||||
}
|
|
||||||
void after_local_1(int) __attribute__((overloadable)); // expected-error {{conflicting types}}
|
|
||||||
void after_local_2(int); // expected-error {{must have the 'overloadable' attribute}}
|
|
||||||
void after_local_3(int) __attribute__((overloadable));
|
|
||||||
|
|
|
@ -3,20 +3,20 @@
|
||||||
namespace test1 {
|
namespace test1 {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void test1_f() {
|
void test1_f() {
|
||||||
void test1_g(int); // expected-note {{declared with C language linkage here}}
|
void test1_g(int); // expected-note {{previous declaration is here}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int test1_g(int); // expected-error {{declaration of 'test1_g' in global scope conflicts with declaration with C language linkage}}
|
int test1_g(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
|
||||||
|
|
||||||
namespace test2 {
|
namespace test2 {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void test2_f() {
|
void test2_f() {
|
||||||
extern int test2_x; // expected-note {{declared with C language linkage here}}
|
extern int test2_x; // expected-note {{previous definition is here}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float test2_x; // expected-error {{declaration of 'test2_x' in global scope conflicts with declaration with C language linkage}}
|
float test2_x; // expected-error {{redefinition of 'test2_x' with a different type: 'float' vs 'int'}}
|
||||||
|
|
||||||
namespace test3 {
|
namespace test3 {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -31,18 +31,18 @@ namespace test3 {
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void test4_f() {
|
void test4_f() {
|
||||||
extern int test4_b; // expected-note {{declared with C language linkage here}}
|
extern int test4_b; // expected-note {{previous definition is here}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static float test4_b; // expected-error {{declaration of 'test4_b' in global scope conflicts with declaration with C language linkage}}
|
static float test4_b; // expected-error {{redefinition of 'test4_b' with a different type: 'float' vs 'int'}}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void test5_f() {
|
void test5_f() {
|
||||||
extern int test5_b; // expected-note {{declared with C language linkage here}}
|
extern int test5_b; // expected-note {{previous definition is here}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
static float test5_b; // expected-error {{declaration of 'test5_b' in global scope conflicts with declaration with C language linkage}}
|
static float test5_b; // expected-error {{redefinition of 'test5_b' with a different type: 'float' vs 'int'}}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -69,11 +69,11 @@ namespace linkage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
namespace from_outer {
|
namespace from_outer {
|
||||||
void linkage_from_outer_1(); // expected-note {{previous}}
|
void linkage_from_outer_1();
|
||||||
void linkage_from_outer_2(); // expected-note {{previous}}
|
void linkage_from_outer_2(); // expected-note {{previous}}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void linkage_from_outer_1(int);
|
void linkage_from_outer_1(int); // expected-note {{previous}}
|
||||||
void linkage_from_outer_1(); // expected-error {{different language linkage}}
|
void linkage_from_outer_1(); // expected-error {{conflicting types}}
|
||||||
void linkage_from_outer_2(); // expected-error {{different language linkage}}
|
void linkage_from_outer_2(); // expected-error {{different language linkage}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,44 +98,11 @@ namespace linkage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lookup_in_global_f(); // expected-note {{here}}
|
void lookup_in_global_f();
|
||||||
namespace lookup_in_global {
|
namespace lookup_in_global {
|
||||||
void lookup_in_global_f();
|
void lookup_in_global_f();
|
||||||
void lookup_in_global_g();
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void lookup_in_global_f(int); // expected-error {{conflicts with declaration in global scope}}
|
// FIXME: We should reject this.
|
||||||
void lookup_in_global_g(int); // expected-note {{here}}
|
void lookup_in_global_f(int);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void lookup_in_global_g(); // expected-error {{conflicts with declaration with C language linkage}}
|
|
||||||
|
|
||||||
namespace N1 {
|
|
||||||
extern "C" int different_kind_1; // expected-note {{here}}
|
|
||||||
extern "C" void different_kind_2(); // expected-note {{here}}
|
|
||||||
}
|
|
||||||
namespace N2 {
|
|
||||||
extern "C" void different_kind_1(); // expected-error {{different kind of symbol}}
|
|
||||||
extern "C" int different_kind_2; // expected-error {{different kind of symbol}}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
struct stat {};
|
|
||||||
void stat(struct stat);
|
|
||||||
}
|
|
||||||
namespace X {
|
|
||||||
extern "C" {
|
|
||||||
void stat(struct ::stat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void name_with_using_decl_1(int);
|
|
||||||
namespace using_decl {
|
|
||||||
void name_with_using_decl_1();
|
|
||||||
void name_with_using_decl_2();
|
|
||||||
void name_with_using_decl_3();
|
|
||||||
}
|
|
||||||
using using_decl::name_with_using_decl_1;
|
|
||||||
using using_decl::name_with_using_decl_2;
|
|
||||||
extern "C" void name_with_using_decl_2(int);
|
|
||||||
extern "C" void name_with_using_decl_3(int);
|
|
||||||
using using_decl::name_with_using_decl_3;
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ namespace test6_3 {
|
||||||
namespace test7 {
|
namespace test7 {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
class X {
|
class X {
|
||||||
friend int test7_f() { return 42; }
|
friend int f() { return 42; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,32 +41,20 @@ namespace pr5430 {
|
||||||
using namespace pr5430;
|
using namespace pr5430;
|
||||||
extern "C" void pr5430::func(void) { }
|
extern "C" void pr5430::func(void) { }
|
||||||
|
|
||||||
// PR5405
|
// PR5404
|
||||||
int f2(char *) // expected-note {{here}}
|
int f2(char *)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
int f2(int) // expected-error {{with C language linkage conflicts with declaration in global scope}}
|
int f2(int)
|
||||||
{
|
{
|
||||||
return f2((char *)0);
|
return f2((char *)0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace PR5405 {
|
|
||||||
int f2b(char *) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
int f2b(int) {
|
|
||||||
return f2b((char *)0); // ok
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PR6991
|
// PR6991
|
||||||
extern "C" typedef int (*PutcFunc_t)(int);
|
extern "C" typedef int (*PutcFunc_t)(int);
|
||||||
|
|
||||||
|
@ -129,28 +117,3 @@ namespace pr14958 {
|
||||||
|
|
||||||
extern "C" void PR16167; // expected-error {{variable has incomplete type 'void'}}
|
extern "C" void PR16167; // expected-error {{variable has incomplete type 'void'}}
|
||||||
extern void PR16167_0; // expected-error {{variable has incomplete type 'void'}}
|
extern void PR16167_0; // expected-error {{variable has incomplete type 'void'}}
|
||||||
|
|
||||||
// PR7927
|
|
||||||
enum T_7927 {
|
|
||||||
E_7927
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" void f_pr7927(int);
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
extern "C" void f_pr7927(int);
|
|
||||||
|
|
||||||
void foo_pr7927() {
|
|
||||||
f_pr7927(E_7927);
|
|
||||||
f_pr7927(0);
|
|
||||||
::f_pr7927(E_7927);
|
|
||||||
::f_pr7927(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bar_pr7927() {
|
|
||||||
f_pr7927(E_7927);
|
|
||||||
f_pr7927(0);
|
|
||||||
::f_pr7927(E_7927);
|
|
||||||
::f_pr7927(0);
|
|
||||||
}
|
|
||||||
|
|
|
@ -201,15 +201,3 @@ namespace test18 {
|
||||||
}
|
}
|
||||||
void *h() { return f(); }
|
void *h() { return f(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void pr16247_foo(int); // expected-note {{here}}
|
|
||||||
static void pr16247_foo(double); // expected-error {{conflicts with declaration with C language linkage}}
|
|
||||||
void pr16247_foo(int) {}
|
|
||||||
void pr16247_foo(double) {}
|
|
||||||
|
|
||||||
namespace PR16247 {
|
|
||||||
extern "C" void pr16247_bar(int);
|
|
||||||
static void pr16247_bar(double);
|
|
||||||
void pr16247_bar(int) {}
|
|
||||||
void pr16247_bar(double) {}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue