From 85910986c4ab01927c192aea86b2234fec568259 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 12 Feb 2010 05:48:04 +0000 Subject: [PATCH] In C++, allow builtins to be referred to via qualified name lookup, e.g., ::__builtin_va_copy Fixes one of the Firefox issues in PR5511. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95966 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.h | 1 - lib/Sema/SemaLookup.cpp | 77 ++++++++++++++++++++++++--------------- test/SemaCXX/builtins.cpp | 2 + 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 5ee790cefe..02ffb8ccb4 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1340,7 +1340,6 @@ public: bool LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS, bool AllowBuiltinCreation = false, bool EnteringContext = false); - ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II); void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 0d95c713b0..c7569d6eda 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -438,9 +438,42 @@ void LookupResult::print(llvm::raw_ostream &Out) { } } +/// \brief Lookup a builtin function, when name lookup would otherwise +/// fail. +static bool LookupBuiltin(Sema &S, LookupResult &R) { + Sema::LookupNameKind NameKind = R.getLookupKind(); + + // If we didn't find a use of this identifier, and if the identifier + // corresponds to a compiler builtin, create the decl object for the builtin + // now, injecting it into translation unit scope, and return it. + if (NameKind == Sema::LookupOrdinaryName || + NameKind == Sema::LookupRedeclarationWithLinkage) { + IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo(); + if (II) { + // If this is a builtin on this (or all) targets, create the decl. + if (unsigned BuiltinID = II->getBuiltinID()) { + // In C++, we don't have any predefined library functions like + // 'malloc'. Instead, we'll just error. + if (S.getLangOptions().CPlusPlus && + S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + return false; + + NamedDecl *D = S.LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, + S.TUScope, R.isForRedeclaration(), + R.getNameLoc()); + if (D) + R.addDecl(D); + return (D != NULL); + } + } + } + + return false; +} + // Adds all qualifying matches for a name within a decl context to the // given lookup result. Returns true if any matches were found. -static bool LookupDirect(LookupResult &R, const DeclContext *DC) { +static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { bool Found = false; DeclContext::lookup_const_iterator I, E; @@ -452,6 +485,9 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) { } } + if (!Found && DC->isTranslationUnit() && LookupBuiltin(S, R)) + return true; + if (R.getLookupName().getNameKind() != DeclarationName::CXXConversionFunctionName || R.getLookupName().getCXXNameType()->isDependentType() || @@ -525,13 +561,13 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) { // Performs C++ unqualified lookup into the given file context. static bool -CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS, - UnqualUsingDirectiveSet &UDirs) { +CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context, + DeclContext *NS, UnqualUsingDirectiveSet &UDirs) { assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!"); // Perform direct name lookup into the LookupCtx. - bool Found = LookupDirect(R, NS); + bool Found = LookupDirect(S, R, NS); // Perform direct name lookup into the namespaces nominated by the // using directives whose common ancestor is this namespace. @@ -539,7 +575,7 @@ CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS, llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS); for (; UI != UEnd; ++UI) - if (LookupDirect(R, UI->getNominatedNamespace())) + if (LookupDirect(S, R, UI->getNominatedNamespace())) Found = true; R.resolveKind(); @@ -670,7 +706,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { "We should have been looking only at file context here already."); // Look into context considering using-directives. - if (CppNamespaceLookup(R, Context, Ctx, UDirs)) + if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) Found = true; } @@ -794,26 +830,9 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { // If we didn't find a use of this identifier, and if the identifier // corresponds to a compiler builtin, create the decl object for the builtin // now, injecting it into translation unit scope, and return it. - if (NameKind == LookupOrdinaryName || - NameKind == LookupRedeclarationWithLinkage) { - IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (II && AllowBuiltinCreation) { - // If this is a builtin on this (or all) targets, create the decl. - if (unsigned BuiltinID = II->getBuiltinID()) { - // In C++, we don't have any predefined library functions like - // 'malloc'. Instead, we'll just error. - if (getLangOptions().CPlusPlus && - Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return false; + if (AllowBuiltinCreation) + return LookupBuiltin(*this, R); - NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, - S, R.isForRedeclaration(), - R.getNameLoc()); - if (D) R.addDecl(D); - return (D != NULL); - } - } - } return false; } @@ -843,7 +862,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { /// class or enumeration name if and only if the declarations are /// from the same namespace; otherwise (the declarations are from /// different namespaces), the program is ill-formed. -static bool LookupQualifiedNameInUsingDirectives(LookupResult &R, +static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, DeclContext *StartDC) { assert(StartDC->isFileContext() && "start context is not a file context"); @@ -886,7 +905,7 @@ static bool LookupQualifiedNameInUsingDirectives(LookupResult &R, // between LookupResults. bool UseLocal = !R.empty(); LookupResult &DirectR = UseLocal ? LocalR : R; - bool FoundDirect = LookupDirect(DirectR, ND); + bool FoundDirect = LookupDirect(S, DirectR, ND); if (FoundDirect) { // First do any local hiding. @@ -966,7 +985,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, "Declaration context must already be complete!"); // Perform qualified name lookup into the LookupCtx. - if (LookupDirect(R, LookupCtx)) { + if (LookupDirect(*this, R, LookupCtx)) { R.resolveKind(); if (isa(LookupCtx)) R.setNamingClass(cast(LookupCtx)); @@ -987,7 +1006,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // If this is a namespace, look it up in the implied namespaces. if (LookupCtx->isFileContext()) - return LookupQualifiedNameInUsingDirectives(R, LookupCtx); + return LookupQualifiedNameInUsingDirectives(*this, R, LookupCtx); // If this isn't a C++ class, we aren't allowed to look into base // classes, we're done. diff --git a/test/SemaCXX/builtins.cpp b/test/SemaCXX/builtins.cpp index a75b4f2e40..568ba5dde1 100644 --- a/test/SemaCXX/builtins.cpp +++ b/test/SemaCXX/builtins.cpp @@ -5,3 +5,5 @@ typedef const struct __CFString * CFStringRef; void f() { (void)CFStringRef(CFSTR("Hello")); } + +void a() { __builtin_va_list x, y; ::__builtin_va_copy(x, y); } -- 2.40.0