r185229 - PR7927, PR16247: Reimplement handling of matching extern "C" declarations
Michael Gottesman
mgottesman at apple.com
Sat Jun 29 02:09:18 PDT 2013
I am seeing a similar issue on Darwin with a bunch of programs in the test-suite (for example Shootout-C++/heapsort.cpp).
Michael
On Jun 29, 2013, at 1:36 AM, Timur Iskhodzhanov <timurrrr at google.com> wrote:
> Hi Richard,
>
> This has broken compilation of <windows.h>:
>
> C:\Program Files (x86)\Microsoft Visual Studio
> 10.0\VC\INCLUDE\stdio.h:276:47: error: declaration of 'gets_s' in
> global scope conflicts with declaration with C language linkage
> __DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_0(char *, gets_s, char, _Buffer)
> ^
> C:\Program Files (x86)\Microsoft Visual Studio
> 10.0\VC\INCLUDE\crtdefs.h:587:27: note: expanded from macro
> '__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_0'
> _ReturnType __CRTDECL _FuncName(_DstType (&_Dst)[_Size])
> _CRT_SECURE_CPP_NOTHROW \
> ^
> C:\Program Files (x86)\Microsoft Visual Studio
> 10.0\VC\INCLUDE\stdio.h:274:24: note: declared with C language linkage
> here
> _CRTIMP char * __cdecl gets_s(_Out_z_cap_(_Size) char * _Buf, _In_
> rsize_t _Size);
> ^
> C:\Program Files (x86)\Microsoft Visual Studio
> 10.0\VC\INCLUDE\stdio.h:319:52: error: declaration of '_snprintf_s' in
> global scope conflicts with declaration with C language linkage
> __DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_2_ARGLIST(int, _snprintf_s,
> _vsnprintf_s, _Deref_post_z_ char, _Dest, _In_ size_t, _MaxCount,
> _In_z_ _Printf_format_string_ const char *,_Format)
> ^
> C:\Program Files (x86)\Microsoft Visual Studio
> 10.0\VC\INCLUDE\crtdefs.h:704:27: note: expanded from macro
> '__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_2_ARGLIST'
> _ReturnType __CRTDECL _FuncName(_DstType (&_Dst)[_Size], _TType1
> _TArg1, _TType2 _TArg2, ...) _CRT_SECURE_CPP_NOTHROW \
> ^
> C:\Program Files (x86)\Microsoft Visual Studio
> 10.0\VC\INCLUDE\stdio.h:318:52: note: declared with C language linkage
> here
> _Check_return_opt_ _CRTIMP_ALTERNATIVE int __cdecl
> _snprintf_s(_Out_z_bytecap_(_SizeInBytes) char * _DstBuf, _In_ size_t
> _SizeInBytes, _In_ size_t _MaxCount, _In_z_ _Printf_format_string_
> const char * _Format, ...);
> ---
>
> I'm going to revert your change to make the bots greener over the weekend.
> Please investigate how extern "C" is used here and add tests to
> prevent new regressions.
>
> --
> Timur
>
> 2013/6/29 Richard Smith <richard-llvm at metafoo.co.uk>:
>> Author: rsmith
>> Date: Fri Jun 28 17:03:51 2013
>> New Revision: 185229
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=185229&view=rev
>> Log:
>> PR7927, PR16247: Reimplement handling of matching extern "C" declarations
>> across scopes.
>>
>> When we declare an extern "C" name that is not a redeclaration of an entity in
>> the same scope, check whether it redeclares some extern "C" entity from another
>> scope, and if not, check whether it conflicts with a (non-extern-"C") entity in
>> the translation unit.
>>
>> When we declare a name in the translation unit that is not a redeclaration,
>> check whether it conflicts with any extern "C" entities (possibly from other
>> scopes).
>>
>> Modified:
>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>> cfe/trunk/lib/Sema/SemaDecl.cpp
>> cfe/trunk/lib/Sema/SemaOverload.cpp
>> cfe/trunk/test/CXX/class.access/class.friend/p1.cpp
>> cfe/trunk/test/Sema/overloadable.c
>> cfe/trunk/test/SemaCXX/extern-c.cpp
>> cfe/trunk/test/SemaCXX/friend.cpp
>> cfe/trunk/test/SemaCXX/linkage-spec.cpp
>> cfe/trunk/test/SemaCXX/linkage2.cpp
>>
>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=185229&r1=185228&r2=185229&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 28 17:03:51 2013
>> @@ -3493,6 +3493,11 @@ 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<
>>
>> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=185229&r1=185228&r2=185229&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jun 28 17:03:51 2013
>> @@ -4359,10 +4359,14 @@ TryToFixInvalidVariablyModifiedTypeSourc
>> /// function-scope declarations.
>> void
>> Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) {
>> - assert(
>> - !ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit() &&
>> - "Decl is not a locally-scoped decl!");
>> + if (!getLangOpts().CPlusPlus &&
>> + ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit())
>> + // Don't need to track declarations in the TU in C.
>> + return;
>> +
>> // 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;
>> }
>>
>> @@ -4681,6 +4685,32 @@ static bool isFunctionDefinitionDiscarde
>> 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) {
>> const DeclContext *DC = VD->getDeclContext()->getRedeclContext();
>> if (DC->isFunctionOrMethod())
>> @@ -5070,16 +5100,10 @@ Sema::ActOnVariableDeclarator(Scope *S,
>> ProcessPragmaWeak(S, NewVD);
>> checkAttributesAfterMerging(*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())
>> + // 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))
>> RegisterLocallyScopedExternCDecl(NewVD, S);
>>
>> return NewVD;
>> @@ -5180,30 +5204,120 @@ void Sema::CheckShadow(Scope *S, VarDecl
>> 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>
>> -static bool mayConflictWithNonVisibleExternC(const T *ND) {
>> - const DeclContext *DC = ND->getDeclContext();
>> - if (DC->getRedeclContext()->isTranslationUnit())
>> - return true;
>> +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());
>> +
>> + if (!Prev && IsGlobal && !isIncompleteDeclExternC(S, ND)) {
>> + // The common case: this global doesn't conflict with any extern "C"
>> + // declaration.
>> + return false;
>> + }
>>
>> - // 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)
>> + 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<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;
>> }
>>
>> - return ND->isExternC();
>> + // 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
>> + // 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;
>> }
>>
>> void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
>> @@ -5386,14 +5500,9 @@ bool Sema::CheckVariableDeclaration(VarD
>> // 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 = false;
>> - if (Previous.empty() && mayConflictWithNonVisibleExternC(NewVD)) {
>> - if (NamedDecl *ExternCPrev =
>> - findLocallyScopedExternCDecl(NewVD->getDeclName())) {
>> - Previous.addDecl(ExternCPrev);
>> - PreviousWasHidden = true;
>> - }
>> - }
>> + bool PreviousWasHidden =
>> + Previous.empty() &&
>> + checkForConflictWithNonVisibleExternC(*this, NewVD, Previous);
>>
>> // Filter out any non-conflicting previous declarations.
>> filterNonConflictingPreviousDecls(Context, NewVD, Previous);
>> @@ -6625,12 +6734,10 @@ Sema::ActOnFunctionDeclarator(Scope *S,
>> // marking the function.
>> AddCFAuditedAttribute(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())
>> + // 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))
>> RegisterLocallyScopedExternCDecl(NewFD, S);
>>
>> // Set this FunctionDecl's range up to the right paren.
>> @@ -6734,15 +6841,6 @@ bool Sema::CheckFunctionDeclaration(Scop
>> 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);
>>
>> @@ -6796,6 +6894,34 @@ bool Sema::CheckFunctionDeclaration(Scop
>> }
>> }
>> }
>> +
>> + // 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:
>> // A constexpr specifier for a non-static member function that is not
>>
>> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=185229&r1=185228&r2=185229&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
>> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Jun 28 17:03:51 2013
>> @@ -977,21 +977,12 @@ Sema::CheckOverload(Scope *S, FunctionDe
>> return Ovl_Overload;
>> }
>>
>> -static bool canBeOverloaded(const FunctionDecl &D) {
>> - if (D.getAttr<OverloadableAttr>())
>> - return true;
>> - if (D.isExternC())
>> - return false;
>> -
>> - // Main cannot be overloaded (basic.start.main).
>> - if (D.isMain())
>> +bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,
>> + bool UseUsingDeclRules) {
>> + // C++ [basic.start.main]p2: This function shall not be overloaded.
>> + if (New->isMain())
>> return false;
>>
>> - return true;
>> -}
>> -
>> -static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,
>> - bool UseUsingDeclRules) {
>> FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
>> FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
>>
>> @@ -1002,8 +993,8 @@ static bool shouldTryToOverload(Sema &S,
>> return true;
>>
>> // Is the function New an overload of the function Old?
>> - QualType OldQType = S.Context.getCanonicalType(Old->getType());
>> - QualType NewQType = S.Context.getCanonicalType(New->getType());
>> + QualType OldQType = Context.getCanonicalType(Old->getType());
>> + QualType NewQType = 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
>> @@ -1024,7 +1015,7 @@ static bool shouldTryToOverload(Sema &S,
>> if (OldQType != NewQType &&
>> (OldType->getNumArgs() != NewType->getNumArgs() ||
>> OldType->isVariadic() != NewType->isVariadic() ||
>> - !S.FunctionArgTypesAreEqual(OldType, NewType)))
>> + !FunctionArgTypesAreEqual(OldType, NewType)))
>> return true;
>>
>> // C++ [temp.over.link]p4:
>> @@ -1040,9 +1031,9 @@ static bool shouldTryToOverload(Sema &S,
>> // However, we don't consider either of these when deciding whether
>> // a member introduced by a shadow declaration is hidden.
>> if (!UseUsingDeclRules && NewTemplate &&
>> - (!S.TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
>> - OldTemplate->getTemplateParameters(),
>> - false, S.TPL_TemplateMatch) ||
>> + (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
>> + OldTemplate->getTemplateParameters(),
>> + false, TPL_TemplateMatch) ||
>> OldType->getResultType() != NewType->getResultType()))
>> return true;
>>
>> @@ -1068,9 +1059,9 @@ static bool shouldTryToOverload(Sema &S,
>> // 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).
>> - S.Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
>> + Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)
>> << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();
>> - S.Diag(OldMethod->getLocation(), diag::note_previous_declaration);
>> + Diag(OldMethod->getLocation(), diag::note_previous_declaration);
>> }
>> return true;
>> }
>> @@ -1080,7 +1071,7 @@ static bool shouldTryToOverload(Sema &S,
>> // or non-static member function). Add it now, on the assumption that this
>> // is a redeclaration of OldMethod.
>> unsigned NewQuals = NewMethod->getTypeQualifiers();
>> - if (!S.getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() &&
>> + if (!getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() &&
>> !isa<CXXConstructorDecl>(NewMethod))
>> NewQuals |= Qualifiers::Const;
>> if (OldMethod->getTypeQualifiers() != NewQuals)
>> @@ -1091,19 +1082,6 @@ static bool shouldTryToOverload(Sema &S,
>> 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.
>> ///
>>
>> Modified: cfe/trunk/test/CXX/class.access/class.friend/p1.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.friend/p1.cpp?rev=185229&r1=185228&r2=185229&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/CXX/class.access/class.friend/p1.cpp (original)
>> +++ cfe/trunk/test/CXX/class.access/class.friend/p1.cpp Fri Jun 28 17:03:51 2013
>> @@ -287,22 +287,22 @@ namespace test9 {
>>
>> // PR7230
>> namespace test10 {
>> - extern "C" void f(void);
>> - extern "C" void g(void);
>> + extern "C" void test10_f(void);
>> + extern "C" void test10_g(void);
>>
>> namespace NS {
>> class C {
>> void foo(void); // expected-note {{declared private here}}
>> - friend void test10::f(void);
>> + friend void test10::test10_f(void);
>> };
>> static C* bar;
>> }
>>
>> - void f(void) {
>> + void test10_f(void) {
>> NS::bar->foo();
>> }
>>
>> - void g(void) {
>> + void test10_g(void) {
>> NS::bar->foo(); // expected-error {{private member}}
>> }
>> }
>>
>> Modified: cfe/trunk/test/Sema/overloadable.c
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/overloadable.c?rev=185229&r1=185228&r2=185229&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/Sema/overloadable.c (original)
>> +++ cfe/trunk/test/Sema/overloadable.c Fri Jun 28 17:03:51 2013
>> @@ -69,3 +69,18 @@ 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));
>>
>> Modified: cfe/trunk/test/SemaCXX/extern-c.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/extern-c.cpp?rev=185229&r1=185228&r2=185229&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/SemaCXX/extern-c.cpp (original)
>> +++ cfe/trunk/test/SemaCXX/extern-c.cpp Fri Jun 28 17:03:51 2013
>> @@ -3,20 +3,20 @@
>> namespace test1 {
>> extern "C" {
>> void test1_f() {
>> - void test1_g(int); // expected-note {{previous declaration is here}}
>> + void test1_g(int); // expected-note {{declared with C language linkage here}}
>> }
>> }
>> }
>> -int test1_g(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}
>> +int test1_g(int); // expected-error {{declaration of 'test1_g' in global scope conflicts with declaration with C language linkage}}
>>
>> namespace test2 {
>> extern "C" {
>> void test2_f() {
>> - extern int test2_x; // expected-note {{previous definition is here}}
>> + extern int test2_x; // expected-note {{declared with C language linkage here}}
>> }
>> }
>> }
>> -float test2_x; // expected-error {{redefinition of 'test2_x' with a different type: 'float' vs 'int'}}
>> +float test2_x; // expected-error {{declaration of 'test2_x' in global scope conflicts with declaration with C language linkage}}
>>
>> namespace test3 {
>> extern "C" {
>> @@ -31,18 +31,18 @@ namespace test3 {
>>
>> extern "C" {
>> void test4_f() {
>> - extern int test4_b; // expected-note {{previous definition is here}}
>> + extern int test4_b; // expected-note {{declared with C language linkage here}}
>> }
>> }
>> -static float test4_b; // expected-error {{redefinition of 'test4_b' with a different type: 'float' vs 'int'}}
>> +static float test4_b; // expected-error {{declaration of 'test4_b' in global scope conflicts with declaration with C language linkage}}
>>
>> extern "C" {
>> void test5_f() {
>> - extern int test5_b; // expected-note {{previous definition is here}}
>> + extern int test5_b; // expected-note {{declared with C language linkage here}}
>> }
>> }
>> extern "C" {
>> - static float test5_b; // expected-error {{redefinition of 'test5_b' with a different type: 'float' vs 'int'}}
>> + static float test5_b; // expected-error {{declaration of 'test5_b' in global scope conflicts with declaration with C language linkage}}
>> }
>>
>> extern "C" {
>> @@ -69,11 +69,11 @@ namespace linkage {
>> }
>> }
>> namespace from_outer {
>> - void linkage_from_outer_1();
>> + void linkage_from_outer_1(); // expected-note {{previous}}
>> void linkage_from_outer_2(); // expected-note {{previous}}
>> extern "C" {
>> - void linkage_from_outer_1(int); // expected-note {{previous}}
>> - void linkage_from_outer_1(); // expected-error {{conflicting types}}
>> + void linkage_from_outer_1(int);
>> + void linkage_from_outer_1(); // expected-error {{different language linkage}}
>> void linkage_from_outer_2(); // expected-error {{different language linkage}}
>> }
>> }
>> @@ -98,11 +98,44 @@ namespace linkage {
>> }
>> }
>>
>> -void lookup_in_global_f();
>> +void lookup_in_global_f(); // expected-note {{here}}
>> namespace lookup_in_global {
>> void lookup_in_global_f();
>> + void lookup_in_global_g();
>> extern "C" {
>> - // FIXME: We should reject this.
>> - void lookup_in_global_f(int);
>> + void lookup_in_global_f(int); // expected-error {{conflicts with declaration in global scope}}
>> + void lookup_in_global_g(int); // expected-note {{here}}
>> }
>> }
>> +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;
>>
>> Modified: cfe/trunk/test/SemaCXX/friend.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/friend.cpp?rev=185229&r1=185228&r2=185229&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/SemaCXX/friend.cpp (original)
>> +++ cfe/trunk/test/SemaCXX/friend.cpp Fri Jun 28 17:03:51 2013
>> @@ -134,7 +134,7 @@ namespace test6_3 {
>> namespace test7 {
>> extern "C" {
>> class X {
>> - friend int f() { return 42; }
>> + friend int test7_f() { return 42; }
>> };
>> }
>> }
>>
>> Modified: cfe/trunk/test/SemaCXX/linkage-spec.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/linkage-spec.cpp?rev=185229&r1=185228&r2=185229&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/SemaCXX/linkage-spec.cpp (original)
>> +++ cfe/trunk/test/SemaCXX/linkage-spec.cpp Fri Jun 28 17:03:51 2013
>> @@ -41,20 +41,32 @@ namespace pr5430 {
>> using namespace pr5430;
>> extern "C" void pr5430::func(void) { }
>>
>> -// PR5404
>> -int f2(char *)
>> +// PR5405
>> +int f2(char *) // expected-note {{here}}
>> {
>> return 0;
>> }
>>
>> extern "C"
>> {
>> - int f2(int)
>> + int f2(int) // expected-error {{with C language linkage conflicts with declaration in global scope}}
>> {
>> 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);
>>
>> @@ -117,3 +129,28 @@ 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);
>> +}
>>
>> Modified: cfe/trunk/test/SemaCXX/linkage2.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/linkage2.cpp?rev=185229&r1=185228&r2=185229&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/SemaCXX/linkage2.cpp (original)
>> +++ cfe/trunk/test/SemaCXX/linkage2.cpp Fri Jun 28 17:03:51 2013
>> @@ -201,3 +201,15 @@ 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) {}
>> +}
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list