int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) { if (LHS.getNameKind() != RHS.getNameKind()) return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1); switch (LHS.getNameKind()) { case DeclarationName::Identifier: { IdentifierInfo *LII = LHS.getAsIdentifierInfo(); IdentifierInfo *RII = RHS.getAsIdentifierInfo(); if (!LII) return RII ? -1 : 0; if (!RII) return 1; return LII->getName().compare(RII->getName()); } case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: { Selector LHSSelector = LHS.getObjCSelector(); Selector RHSSelector = RHS.getObjCSelector(); unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs(); for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) { switch (LHSSelector.getNameForSlot(I).compare( RHSSelector.getNameForSlot(I))) { case -1: return true; case 1: return false; default: break; } } return compareInt(LN, RN); } case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType())) return -1; if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType())) return 1; return 0; case DeclarationName::CXXOperatorName: return compareInt(LHS.getCXXOverloadedOperator(), RHS.getCXXOverloadedOperator()); case DeclarationName::CXXLiteralOperatorName: return LHS.getCXXLiteralIdentifier()->getName().compare( RHS.getCXXLiteralIdentifier()->getName()); case DeclarationName::CXXUsingDirective: return 0; } return 0; }
DeclarationNameLoc::DeclarationNameLoc(DeclarationName Name) { switch (Name.getNameKind()) { case DeclarationName::Identifier: break; case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: NamedType.TInfo = nullptr; break; case DeclarationName::CXXOperatorName: CXXOperatorName.BeginOpNameLoc = SourceLocation().getRawEncoding(); CXXOperatorName.EndOpNameLoc = SourceLocation().getRawEncoding(); break; case DeclarationName::CXXLiteralOperatorName: CXXLiteralOperatorName.OpNameLoc = SourceLocation().getRawEncoding(); break; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: // FIXME: ? break; case DeclarationName::CXXUsingDirective: break; } }
void RemoveUnusedFunction::handleOneCXXDependentScopeMemberExpr( const FunctionDecl *CurrentFD, const CXXDependentScopeMemberExpr *E) { if (E->isImplicitAccess()) return; DeclarationName DName = E->getMember(); DeclarationName::NameKind K = DName.getNameKind(); if ((K != DeclarationName::CXXOperatorName) && (K != DeclarationName::Identifier)) return; const Expr *Base = E->getBase()->IgnoreParenCasts(); const FunctionDecl *FD = NULL; if (dyn_cast<CXXThisExpr>(Base)) { TransAssert(CurrentFD && "NULL CurrentFD"); const DeclContext *Ctx = CurrentFD->getLookupParent(); TransAssert(Ctx && "Bad DeclContext!"); DeclContextSet VisitedCtxs; FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs); // we may not get FD in cases where we have this->m_field if (FD) addOneReferencedFunction(FD); return; } }
bool operator<(DeclarationName LHS, DeclarationName RHS) { if (LHS.getNameKind() != RHS.getNameKind()) return LHS.getNameKind() < RHS.getNameKind(); switch (LHS.getNameKind()) { case DeclarationName::Identifier: return LHS.getAsIdentifierInfo()->getName() < RHS.getAsIdentifierInfo()->getName(); case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: { Selector LHSSelector = LHS.getObjCSelector(); Selector RHSSelector = RHS.getObjCSelector(); for (unsigned I = 0, N = std::min(LHSSelector.getNumArgs(), RHSSelector.getNumArgs()); I != N; ++I) { IdentifierInfo *LHSId = LHSSelector.getIdentifierInfoForSlot(I); IdentifierInfo *RHSId = RHSSelector.getIdentifierInfoForSlot(I); if (!LHSId || !RHSId) return LHSId && !RHSId; switch (LHSId->getName().compare(RHSId->getName())) { case -1: return true; case 1: return false; default: break; } } return LHSSelector.getNumArgs() < RHSSelector.getNumArgs(); } case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: return QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()); case DeclarationName::CXXOperatorName: return LHS.getCXXOverloadedOperator() < RHS.getCXXOverloadedOperator(); case DeclarationName::CXXUsingDirective: return false; } return false; }
void ODRHash::AddDeclarationName(DeclarationName Name) { // Index all DeclarationName and use index numbers to refer to them. auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size())); ID.AddInteger(Result.first->second); if (!Result.second) { // If found in map, the the DeclarationName has previously been processed. return; } // First time processing each DeclarationName, also process its details. AddBoolean(Name.isEmpty()); if (Name.isEmpty()) return; auto Kind = Name.getNameKind(); ID.AddInteger(Kind); switch (Kind) { case DeclarationName::Identifier: AddIdentifierInfo(Name.getAsIdentifierInfo()); break; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: { Selector S = Name.getObjCSelector(); AddBoolean(S.isNull()); AddBoolean(S.isKeywordSelector()); AddBoolean(S.isUnarySelector()); unsigned NumArgs = S.getNumArgs(); for (unsigned i = 0; i < NumArgs; ++i) { AddIdentifierInfo(S.getIdentifierInfoForSlot(i)); } break; } case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: AddQualType(Name.getCXXNameType()); break; case DeclarationName::CXXOperatorName: ID.AddInteger(Name.getCXXOverloadedOperator()); break; case DeclarationName::CXXLiteralOperatorName: AddIdentifierInfo(Name.getCXXLiteralIdentifier()); break; case DeclarationName::CXXConversionFunctionName: AddQualType(Name.getCXXNameType()); break; case DeclarationName::CXXUsingDirective: break; case DeclarationName::CXXDeductionGuideName: { auto *Template = Name.getCXXDeductionGuideTemplate(); AddBoolean(Template); if (Template) { AddDecl(Template); } } } }
void ODRHash::AddDeclarationName(DeclarationName Name) { AddBoolean(Name.isEmpty()); if (Name.isEmpty()) return; auto Kind = Name.getNameKind(); ID.AddInteger(Kind); switch (Kind) { case DeclarationName::Identifier: AddIdentifierInfo(Name.getAsIdentifierInfo()); break; case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: { Selector S = Name.getObjCSelector(); AddBoolean(S.isNull()); AddBoolean(S.isKeywordSelector()); AddBoolean(S.isUnarySelector()); unsigned NumArgs = S.getNumArgs(); for (unsigned i = 0; i < NumArgs; ++i) { AddIdentifierInfo(S.getIdentifierInfoForSlot(i)); } break; } case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: AddQualType(Name.getCXXNameType()); break; case DeclarationName::CXXOperatorName: ID.AddInteger(Name.getCXXOverloadedOperator()); break; case DeclarationName::CXXLiteralOperatorName: AddIdentifierInfo(Name.getCXXLiteralIdentifier()); break; case DeclarationName::CXXConversionFunctionName: AddQualType(Name.getCXXNameType()); break; case DeclarationName::CXXUsingDirective: break; case DeclarationName::CXXDeductionGuideName: { auto *Template = Name.getCXXDeductionGuideTemplate(); AddBoolean(Template); if (Template) { AddDecl(Template); } } } }
// The core lookup interface. DeclContext::lookup_result ClangASTSource::FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { switch (Name.getNameKind()) { // Normal identifiers. case DeclarationName::Identifier: break; // Operator names. Not important for now. case DeclarationName::CXXOperatorName: case DeclarationName::CXXLiteralOperatorName: return DeclContext::lookup_result(); // Using directives found in this context. // Tell Sema we didn't find any or we'll end up getting asked a *lot*. case DeclarationName::CXXUsingDirective: return SetNoExternalVisibleDeclsForName(DC, Name); // These aren't looked up like this. case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: return DeclContext::lookup_result(); // These aren't possible in the global context. case DeclarationName::CXXConstructorName: case DeclarationName::CXXDestructorName: case DeclarationName::CXXConversionFunctionName: return DeclContext::lookup_result(); } llvm::SmallVector<NamedDecl*, 4> Decls; NameSearchContext NSC(*this, Decls, Name, DC); DeclMap.GetDecls(NSC, Name.getAsString().c_str()); return SetExternalVisibleDeclsForName(DC, Name, Decls); }
void RemoveUnusedFunction::handleOneUnresolvedLookupExpr( const FunctionDecl *CurrentFD, const UnresolvedLookupExpr *E) { DeclarationName DName = E->getName(); DeclarationName::NameKind K = DName.getNameKind(); if ((K != DeclarationName::CXXOperatorName) && (K != DeclarationName::Identifier)) return; const NestedNameSpecifier *NNS = E->getQualifier(); // we fail only if UE is invoked with some qualifier or // instantiation, e.g.: // namespace NS { template<typename T> void foo(T&) { } } // template<typename T> void bar(T p) { NS::foo(p); } // removing foo would fail. // // template <typename T> void foo() { } // template <typename T> void bar() { foo<T>(); } // removing foo would faill, too // // On the other handle, the following code is ok: // template<typename T> void foo(T&) { } // template<typename T> void bar(T p) { foo(p); } const FunctionDecl *FD = NULL; if (NNS) { FD = getFunctionDeclFromSpecifier(DName, NNS); } else { const DeclContext *Ctx = CurrentFD->getLookupParent(); FD = lookupFunctionDeclShallow(DName, Ctx); } if (!FD || FD->isReferenced()) return; addOneReferencedFunction(FD); }
bool RewriteUtils::replaceFunctionDeclName(const FunctionDecl *FD, const std::string &NameStr) { // We cannot naively use FD->getNameAsString() here. // For example, for a template class // template<typename T> // class SomeClass { // public: // SomeClass() {} // }; // applying getNameAsString() on SomeClass() gives us SomeClass<T>. DeclarationNameInfo NameInfo = FD->getNameInfo(); DeclarationName DeclName = NameInfo.getName(); DeclarationName::NameKind K = DeclName.getNameKind(); TransAssert((K != DeclarationName::CXXDestructorName) && "Cannot rename CXXDestructorName here!"); std::string FDName = FD->getNameAsString(); size_t FDNameLen = FD->getNameAsString().length(); if (K == DeclarationName::CXXConstructorName) { const Type *Ty = DeclName.getCXXNameType().getTypePtr(); if (Ty->getTypeClass() == Type::InjectedClassName) { const CXXRecordDecl *CXXRD = Ty->getAsCXXRecordDecl(); std::string RDName = CXXRD->getNameAsString(); FDNameLen = FDName.find(RDName); TransAssert((FDNameLen != std::string::npos) && "Cannot find RecordDecl Name!"); FDNameLen += RDName.length(); } } return !TheRewriter->ReplaceText(NameInfo.getLoc(), FDNameLen, NameStr); }
void MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, DeclarationName Name) { // <unqualified-name> ::= <operator-name> // ::= <ctor-dtor-name> // ::= <source-name> switch (Name.getNameKind()) { case DeclarationName::Identifier: { if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { mangleSourceName(II); break; } // Otherwise, an anonymous entity. We must have a declaration. assert(ND && "mangling empty name without declaration"); if (const NamespaceDecl *NS = dyn_cast<NamespaceDecl>(ND)) { if (NS->isAnonymousNamespace()) { Out << "?A"; break; } } // We must have an anonymous struct. const TagDecl *TD = cast<TagDecl>(ND); if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) { assert(TD->getDeclContext() == D->getDeclContext() && "Typedef should not be in another decl context!"); assert(D->getDeclName().getAsIdentifierInfo() && "Typedef was not named!"); mangleSourceName(D->getDeclName().getAsIdentifierInfo()); break; } // When VC encounters an anonymous type with no tag and no typedef, // it literally emits '<unnamed-tag>'. Out << "<unnamed-tag>"; break; } case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: case DeclarationName::ObjCMultiArgSelector: assert(false && "Can't mangle Objective-C selector names here!"); break; case DeclarationName::CXXConstructorName: assert(false && "Can't mangle constructors yet!"); break; case DeclarationName::CXXDestructorName: assert(false && "Can't mangle destructors yet!"); break; case DeclarationName::CXXConversionFunctionName: // <operator-name> ::= ?B # (cast) // The target type is encoded as the return type. Out << "?B"; break; case DeclarationName::CXXOperatorName: mangleOperatorName(Name.getCXXOverloadedOperator()); break; case DeclarationName::CXXLiteralOperatorName: // FIXME: Was this added in VS2010? Does MS even know how to mangle this? assert(false && "Don't know how to mangle literal operators yet!"); break; case DeclarationName::CXXUsingDirective: assert(false && "Can't mangle a using directive name!"); break; } }
void RemoveNestedFunction::getNewTmpVariableStr(ASTContext &ASTCtx, std::string &VarStr) { std::stringstream SS; unsigned int NamePostfix = NameQueryWrap->getMaxNamePostfix(); SS << RewriteHelper->getTmpVarNamePrefix() << (NamePostfix + 1); VarStr = SS.str(); setTmpVarName(VarStr); QualType QT; const Expr *E = TheCallExpr->getCallee(); if (const UnresolvedLookupExpr *UE = dyn_cast<UnresolvedLookupExpr>(E)) { // clang doesn't always resolve CallExpr's callee. For example: // template<typename T> int foo1(int p) {return p;} // template<typename T> int foo2(int p) {return p;} // template<typename T> // void bar(void) { foo1<T>(foo2<T>(1)); } // foo2<T>(1) has BuiltinType and hence // TheCallExpr->getCallReturnType() will segfault. // In this case, we have to lookup a corresponding function decl DeclarationName DName = UE->getName(); TransAssert(((DName.getNameKind() == DeclarationName::Identifier) || (DName.getNameKind() == DeclarationName::CXXOperatorName)) && "Not an indentifier!"); const FunctionDecl *FD = NULL; if (const NestedNameSpecifier *NNS = UE->getQualifier()) { if (const DeclContext *Ctx = getDeclContextFromSpecifier(NNS)) { DeclContextSet VisitedCtxs; FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs); } } if (!FD) { DeclContextSet VisitedCtxs; FD = lookupFunctionDecl(DName, TheFuncDecl->getLookupParent(), VisitedCtxs); } // give up and generate a tmp var of int type, e.g.: // template <class T> struct S { // T x; // template <class A> void foo(A &a0) { x(y(a0)); } // }; if (!FD) return getNewIntTmpVariable(VarStr); QT = FD->getReturnType(); //FIXME: This is actually not quite correct, we should get the instantiated // type here. return getNewTmpVariable(QT, VarStr); } if (const UnresolvedMemberExpr *UM = dyn_cast<UnresolvedMemberExpr>(E)) { DeclarationName DName = UM->getMemberName(); CXXRecordDecl *CXXRD = UM->getNamingClass(); DeclContextSet VisitedCtxs; const FunctionDecl *FD = lookupFunctionDecl(DName, CXXRD, VisitedCtxs); // FIXME: try to resolve FD here if (FD) QT = FD->getReturnType(); return getNewTmpVariable(QT, VarStr); } if (const CXXTemporaryObjectExpr *CXXTE = dyn_cast<CXXTemporaryObjectExpr>(E)) { const CXXConstructorDecl *CXXCtor = CXXTE->getConstructor(); QT = CXXCtor->getThisType(ASTCtx); return getNewTmpVariable(QT, VarStr); } if (const CXXTemporaryObjectExpr *CXXTE = dyn_cast<CXXTemporaryObjectExpr>(E)) { const CXXConstructorDecl *CXXCtor = CXXTE->getConstructor(); QT = CXXCtor->getThisType(ASTCtx); return getNewTmpVariable(QT, VarStr); } if (const CXXDependentScopeMemberExpr *ME = dyn_cast<CXXDependentScopeMemberExpr>(E)) { if (ME->isImplicitAccess()) return; DeclarationName DName = ME->getMember(); TransAssert((DName.getNameKind() == DeclarationName::Identifier) && "Not an indentifier!"); const Expr *E = ME->getBase(); TransAssert(E && "NULL Base Expr!"); const Expr *BaseE = E->IgnoreParens(); // handle cases where base expr or member name is dependent, e.g., // template<typename T> // class S { // int f1(int p1) { return p1; }; // int f2(int p2) { return p2; }; // void f3(void); // }; // template<typename T> // void S<T>::f3(void) // { // f1(this->f2(1)); // } // where this->f2(1) is a CXXDependentScopeMemberExpr if (dyn_cast<CXXThisExpr>(BaseE)) { const DeclContext *Ctx = TheFuncDecl->getLookupParent(); TransAssert(Ctx && "Bad DeclContext!"); DeclContextSet VisitedCtxs; const FunctionDecl *FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs); TransAssert(FD && "Cannot resolve DName!"); QT = FD->getReturnType(); return getNewTmpVariable(QT, VarStr); } // handle other cases where lookupDeclContext is different from // the current CXXRecord, e.g., const Type *Ty = ME->getBaseType().getTypePtr(); if (const DeclContext *Ctx = getBaseDeclFromType(Ty)) { DeclContextSet VisitedCtxs; const FunctionDecl *FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs); if (!FD) { return getNewTmpVariable(QT, VarStr); } QT = FD->getReturnType(); const Type *RVTy = QT.getTypePtr(); if (RVTy->getAs<InjectedClassNameType>()) { // handle cases like: // template <typename> struct D { // D f(); // }; // template <typename T> void foo(D<T>); // template <typename T > void bar () { // D<T> G; // foo(G.f()); // } // in this case, seems it's hard to retrieve the instantiated type // of f's return type, because `D<T> G' is dependent. I tried // findSpecialization from ClassTemplateDecl, but it didn't work. // So use a really ugly way, i.e., manipulating strings... const TemplateSpecializationType *TST = Ty->getAs<TemplateSpecializationType>(); TransAssert(TST && "Invalid TemplateSpecialization Type!"); QT.getAsStringInternal(VarStr, Context->getPrintingPolicy()); return getVarStrForTemplateSpecialization(VarStr, TST); } else { // other cases: // template <typename> struct D { // int f(); // }; // void foo(int); // template <typename T > void bar () { // D<T> G; // foo(G.f()); // } return getNewTmpVariable(QT, VarStr); } } else { // template <typename> struct D { // D f(); // D operator[] (int); // }; // template <typename T> void foo(D<T>); // template <typename T > void bar () { // D<T> G; // foo(G[0].f()); // } // In this case, G[0] is of BuiltinType. // But why does clang represent a dependent type as BuiltinType here? TransAssert((Ty->getAs<BuiltinType>() || Ty->getAs<TemplateTypeParmType>() || Ty->getAs<TypedefType>() || Ty->getAs<DependentNameType>()) && "Uncaught Type"); // FIXME: This is incorrect! // a couple of questions // - how can we find a correct DeclContext where we could lookup f? // - can we obtain the dependent template argument from BuiltinType? // Probably we cannot do these? Comments from lib/AST/ASTContext.cpp: // // Placeholder type for type-dependent expressions whose type is // completely unknown. No code should ever check a type against // DependentTy and users should never see it; however, it is here to // help diagnose failures to properly check for type-dependent // expressions. return getNewIntTmpVariable(VarStr); } } const Type *CalleeType = E->getType().getTypePtr(); // template <class T1, class T2> struct S { // T1 x; T2 y; // template <class A> void foo(A &a0) { x(y(a0)); } // }; if (const TemplateTypeParmType *PT = dyn_cast<TemplateTypeParmType>(CalleeType)) { const TemplateTypeParmDecl *PD = PT->getDecl(); std::string DStr = PD->getNameAsString(); VarStr = DStr + " " + VarStr; return; } QT = TheCallExpr->getCallReturnType(ASTCtx); getNewTmpVariable( QT.getTypePtr()->getUnqualifiedDesugaredType()->getCanonicalTypeInternal(), VarStr); }