r185229 - PR7927, PR16247: Reimplement handling of matching extern "C" declarations
Timur Iskhodzhanov
timurrrr at google.com
Mon Jul 1 01:47:10 PDT 2013
The bots look healthy after the change, thanks!
2013/6/30 Richard Smith <richard at metafoo.co.uk>:
> Thanks for the speedy revert; reinstated with a fix in r185281. We're
> now very nearly completely ignoring this rule in the standard (except
> when a global *variable* conflicts with an extern "C" declaration,
> when we still error because the mangled names are the same in some
> circumstances). If this is still a problem, we can downgrade the
> diagnostic to an extension in the MS ABI (where I believe even global
> variables get mangled names).
>
> On Sat, Jun 29, 2013 at 8:23 AM, Reid Kleckner <rnk at google.com> wrote:
>> I know, I yelled at him in person yesterday. :) He said the logic should
>> probably be disabled for -fms-compatibility. But I'm OK with letting him
>> fix that and roll it back in.
>>
>>
>> On Sat, 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