From 32d1e730237cd925cddaec6af67d85204080301d Mon Sep 17 00:00:00 2001 From: Timur Iskhodzhanov Date: Sat, 29 Jun 2013 08:38:42 +0000 Subject: [PATCH] Revert r185229 as it breaks compilation of llvm-svn: 185256 --- .../clang/Basic/DiagnosticSemaKinds.td | 5 - clang/lib/Sema/SemaDecl.cpp | 236 ++++-------------- clang/lib/Sema/SemaOverload.cpp | 48 +++- .../test/CXX/class.access/class.friend/p1.cpp | 10 +- clang/test/Sema/overloadable.c | 15 -- clang/test/SemaCXX/extern-c.cpp | 61 ++--- clang/test/SemaCXX/friend.cpp | 2 +- clang/test/SemaCXX/linkage-spec.cpp | 43 +--- clang/test/SemaCXX/linkage2.cpp | 12 - 9 files changed, 113 insertions(+), 319 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 77fe76efd16d..54157b317abe 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3493,11 +3493,6 @@ def err_static_non_static : Error< "static declaration of %0 follows non-static declaration">; def err_different_language_linkage : Error< "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 < "an already-declared variable is made a weak_import declaration %0">; def warn_static_non_static : ExtWarn< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9f9bf1e39c78..a87cf61ccfe1 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4359,14 +4359,10 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo, /// function-scope declarations. void Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) { - if (!getLangOpts().CPlusPlus && - ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit()) - // Don't need to track declarations in the TU in C. - return; - + assert( + !ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit() && + "Decl is not a locally-scoped decl!"); // 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; } @@ -4685,32 +4681,6 @@ static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) { 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 -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()) - return false; - } - return D->isExternC(); -} - static bool shouldConsiderLinkage(const VarDecl *VD) { const DeclContext *DC = VD->getDeclContext()->getRedeclContext(); if (DC->isFunctionOrMethod()) @@ -5100,10 +5070,16 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, ProcessPragmaWeak(S, NewVD); checkAttributesAfterMerging(*this, *NewVD); - // If this is the first declaration of an extern C variable, update - // the map of such variables. - if (!NewVD->getPreviousDecl() && !NewVD->isInvalidDecl() && - isIncompleteDeclExternC(*this, NewVD)) + // If this is the first declaration of an extern C variable that is not + // declared directly in the translation unit, update the map of such + // variables. + 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); return NewVD; @@ -5204,120 +5180,30 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) { 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 -static bool checkGlobalOrExternCConflict( - Sema &S, const T *ND, bool IsGlobal, LookupResult &Previous) { - assert(S.getLangOpts().CPlusPlus && "only C++ has extern \"C\""); - NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName()); +static bool mayConflictWithNonVisibleExternC(const T *ND) { + const DeclContext *DC = ND->getDeclContext(); + if (DC->getRedeclContext()->isTranslationUnit()) + return true; - 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; - } - - // This is a global, non-extern "C" declaration, and there is a previous - // non-global extern "C" declaration. Diagnose. - } else { - // The declaration is extern "C". Check for any declaration in the - // 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(*I) || isa(*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(*I) || isa(*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) + // We know that is the first decl we see, other than function local + // extern C ones. If this is C++ and the decl is not in a extern C context + // it cannot have C language linkage. Avoid calling isExternC in that case. + // We need to this because of code like + // + // namespace { struct bar {}; } + // auto foo = bar(); + // + // This code runs before the init of foo is set, and therefore before + // the type of foo is known. Not knowing the type we cannot know its linkage + // unless it is in an extern C block. + if (!ND->isInExternCContext()) { + const ASTContext &Context = ND->getASTContext(); + if (Context.getLangOpts().CPlusPlus) 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(Prev)) - Prev = FD->getFirstDeclaration(); - else - Prev = cast(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 -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 - // set the semantic DC for an extern local variable to be the innermost - // enclosing namespace, and ensure they are only found by redeclaration - // lookup. - if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit()) { - if (NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName())) { - Previous.clear(); - Previous.addDecl(Prev); - return true; - } - } - return false; - } - - // A declaration in the translation unit can conflict with an extern "C" - // 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; + return ND->isExternC(); } 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 // update our understanding of the type according to declarations // not in scope. - bool PreviousWasHidden = - Previous.empty() && - checkForConflictWithNonVisibleExternC(*this, NewVD, Previous); + bool PreviousWasHidden = false; + if (Previous.empty() && mayConflictWithNonVisibleExternC(NewVD)) { + if (NamedDecl *ExternCPrev = + findLocallyScopedExternCDecl(NewVD->getDeclName())) { + Previous.addDecl(ExternCPrev); + PreviousWasHidden = true; + } + } // Filter out any non-conflicting previous declarations. filterNonConflictingPreviousDecls(Context, NewVD, Previous); @@ -6734,10 +6625,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // marking the function. AddCFAuditedAttribute(NewFD); - // If this is the first declaration of an extern C variable, update - // the map of such variables. - if (!NewFD->getPreviousDecl() && !NewFD->isInvalidDecl() && - isIncompleteDeclExternC(*this, NewFD)) + // If this is the first declaration of an extern C variable that is not + // declared directly in the translation unit, update the map of such + // variables. + if (!CurContext->getRedeclContext()->isTranslationUnit() && + !NewFD->getPreviousDecl() && NewFD->isExternC() && + !NewFD->isInvalidDecl()) RegisterLocallyScopedExternCDecl(NewFD, S); // 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() && "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. 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()) { - if (!getLangOpts().CPlusPlus && !NewFD->hasAttr()) { - 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(OldDecl), false)) { - Redeclaration = false; - OldDecl = 0; - } - } - } - } - // C++11 [dcl.constexpr]p8: // A constexpr specifier for a non-static member function that is not // a constructor declares that member function to be const. diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 42eced466eca..3f7ab1c90f11 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -977,12 +977,21 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, return Ovl_Overload; } -bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, - bool UseUsingDeclRules) { - // C++ [basic.start.main]p2: This function shall not be overloaded. - if (New->isMain()) +static bool canBeOverloaded(const FunctionDecl &D) { + if (D.getAttr()) + return true; + if (D.isExternC()) 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 *NewTemplate = New->getDescribedFunctionTemplate(); @@ -993,8 +1002,8 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, return true; // Is the function New an overload of the function Old? - QualType OldQType = Context.getCanonicalType(Old->getType()); - QualType NewQType = Context.getCanonicalType(New->getType()); + QualType OldQType = S.Context.getCanonicalType(Old->getType()); + QualType NewQType = S.Context.getCanonicalType(New->getType()); // Compare the signatures (C++ 1.3.10) of the two functions to // determine whether they are overloads. If we find any mismatch @@ -1015,7 +1024,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, if (OldQType != NewQType && (OldType->getNumArgs() != NewType->getNumArgs() || OldType->isVariadic() != NewType->isVariadic() || - !FunctionArgTypesAreEqual(OldType, NewType))) + !S.FunctionArgTypesAreEqual(OldType, NewType))) return true; // 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 // a member introduced by a shadow declaration is hidden. if (!UseUsingDeclRules && NewTemplate && - (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), - OldTemplate->getTemplateParameters(), - false, TPL_TemplateMatch) || + (!S.TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), + OldTemplate->getTemplateParameters(), + false, S.TPL_TemplateMatch) || OldType->getResultType() != NewType->getResultType())) return true; @@ -1059,9 +1068,9 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, // declarations with the same name, the same parameter-type-list, and // the same template parameter lists cannot be overloaded if any of // 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(); - Diag(OldMethod->getLocation(), diag::note_previous_declaration); + S.Diag(OldMethod->getLocation(), diag::note_previous_declaration); } 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 // is a redeclaration of OldMethod. unsigned NewQuals = NewMethod->getTypeQualifiers(); - if (!getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() && + if (!S.getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() && !isa(NewMethod)) NewQuals |= Qualifiers::Const; if (OldMethod->getTypeQualifiers() != NewQuals) @@ -1082,6 +1091,19 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, 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 /// function context. Inside an unavailable function, unavailability is ignored. /// diff --git a/clang/test/CXX/class.access/class.friend/p1.cpp b/clang/test/CXX/class.access/class.friend/p1.cpp index 1a519dcc3e54..19d94cfdd5f6 100644 --- a/clang/test/CXX/class.access/class.friend/p1.cpp +++ b/clang/test/CXX/class.access/class.friend/p1.cpp @@ -287,22 +287,22 @@ namespace test9 { // PR7230 namespace test10 { - extern "C" void test10_f(void); - extern "C" void test10_g(void); + extern "C" void f(void); + extern "C" void g(void); namespace NS { class C { void foo(void); // expected-note {{declared private here}} - friend void test10::test10_f(void); + friend void test10::f(void); }; static C* bar; } - void test10_f(void) { + void f(void) { NS::bar->foo(); } - void test10_g(void) { + void g(void) { NS::bar->foo(); // expected-error {{private member}} } } diff --git a/clang/test/Sema/overloadable.c b/clang/test/Sema/overloadable.c index ad021898f2a0..5d39f15ec81f 100644 --- a/clang/test/Sema/overloadable.c +++ b/clang/test/Sema/overloadable.c @@ -69,18 +69,3 @@ void test() { f0(); 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)); diff --git a/clang/test/SemaCXX/extern-c.cpp b/clang/test/SemaCXX/extern-c.cpp index aacc0ffb1584..220b2a8dc1e5 100644 --- a/clang/test/SemaCXX/extern-c.cpp +++ b/clang/test/SemaCXX/extern-c.cpp @@ -3,20 +3,20 @@ namespace test1 { extern "C" { 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 { extern "C" { 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 { extern "C" { @@ -31,18 +31,18 @@ namespace test3 { extern "C" { 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" { 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" { - 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" { @@ -69,11 +69,11 @@ namespace linkage { } } namespace from_outer { - void linkage_from_outer_1(); // expected-note {{previous}} + void linkage_from_outer_1(); void linkage_from_outer_2(); // expected-note {{previous}} extern "C" { - void linkage_from_outer_1(int); - void linkage_from_outer_1(); // expected-error {{different language linkage}} + void linkage_from_outer_1(int); // expected-note {{previous}} + void linkage_from_outer_1(); // expected-error {{conflicting types}} 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 { void lookup_in_global_f(); - void lookup_in_global_g(); extern "C" { - void lookup_in_global_f(int); // expected-error {{conflicts with declaration in global scope}} - void lookup_in_global_g(int); // expected-note {{here}} + // FIXME: We should reject this. + 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; diff --git a/clang/test/SemaCXX/friend.cpp b/clang/test/SemaCXX/friend.cpp index ce2f34ff6b98..5daadf0e7297 100644 --- a/clang/test/SemaCXX/friend.cpp +++ b/clang/test/SemaCXX/friend.cpp @@ -134,7 +134,7 @@ namespace test6_3 { namespace test7 { extern "C" { class X { - friend int test7_f() { return 42; } + friend int f() { return 42; } }; } } diff --git a/clang/test/SemaCXX/linkage-spec.cpp b/clang/test/SemaCXX/linkage-spec.cpp index 355a87879310..fc14081247a3 100644 --- a/clang/test/SemaCXX/linkage-spec.cpp +++ b/clang/test/SemaCXX/linkage-spec.cpp @@ -41,32 +41,20 @@ namespace pr5430 { using namespace pr5430; extern "C" void pr5430::func(void) { } -// PR5405 -int f2(char *) // expected-note {{here}} +// PR5404 +int f2(char *) { return 0; } extern "C" { - int f2(int) // expected-error {{with C language linkage conflicts with declaration in global scope}} + int f2(int) { return f2((char *)0); } } -namespace PR5405 { - int f2b(char *) { - return 0; - } - - extern "C" { - int f2b(int) { - return f2b((char *)0); // ok - } - } -} - // PR6991 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 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); -} diff --git a/clang/test/SemaCXX/linkage2.cpp b/clang/test/SemaCXX/linkage2.cpp index c97a2f4ba746..a811575c612e 100644 --- a/clang/test/SemaCXX/linkage2.cpp +++ b/clang/test/SemaCXX/linkage2.cpp @@ -201,15 +201,3 @@ namespace test18 { } 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) {} -}