r185229 - PR7927, PR16247: Reimplement handling of matching extern "C" declarations

Richard Smith richard at metafoo.co.uk
Sun Jun 30 02:53:08 PDT 2013


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