bool GetFields( RecordDecl * rd, Obj * entries) { //check the fields of this struct, if any one of them is not understandable, then this struct becomes 'opaque' //that is, we insert the type, and link it to its llvm type, so it can be used in terra code //but none of its fields are exposed (since we don't understand the layout) bool opaque = false; for(RecordDecl::field_iterator it = rd->field_begin(), end = rd->field_end(); it != end; ++it) { if(it->isBitField() || it->isAnonymousStructOrUnion() || !it->getDeclName()) { opaque = true; continue; } DeclarationName declname = it->getDeclName(); std::string declstr = declname.getAsString(); QualType FT = it->getType(); Obj fobj; if(!GetType(FT,&fobj)) { opaque = true; continue; } lua_newtable(L); fobj.push(); lua_setfield(L,-2,"type"); lua_pushstring(L,declstr.c_str()); lua_setfield(L,-2,"field"); entries->addentry(); } return !opaque; }
bool VisitFunctionDecl(FunctionDecl *f) { // Only function definitions (with bodies), not declarations. if (f->hasBody()) { Stmt *FuncBody = f->getBody(); // Type name as string QualType QT = f->getResultType(); string TypeStr = QT.getAsString(); // Function name DeclarationName DeclName = f->getNameInfo().getName(); string FuncName = DeclName.getAsString(); // Add comment before stringstream SSBefore; SSBefore << "// Begin function " << FuncName << " returning " << TypeStr << "\n"; SourceLocation ST = f->getSourceRange().getBegin(); TheRewriter.InsertText(ST, SSBefore.str(), true, true); // And after stringstream SSAfter; SSAfter << "\n// End function " << FuncName << "\n"; ST = FuncBody->getLocEnd().getLocWithOffset(1); TheRewriter.InsertText(ST, SSAfter.str(), true, true); } return true; }
/// \brief Retrieve the name that should be used to order a result. /// /// If the name needs to be constructed as a string, that string will be /// saved into Saved and the returned StringRef will refer to it. static StringRef getOrderedName(const CodeCompletionResult &R, std::string &Saved) { switch (R.Kind) { case CodeCompletionResult::RK_Keyword: return R.Keyword; case CodeCompletionResult::RK_Pattern: return R.Pattern->getTypedText(); case CodeCompletionResult::RK_Macro: return R.Macro->getName(); case CodeCompletionResult::RK_Declaration: // Handle declarations below. break; } DeclarationName Name = R.Declaration->getDeclName(); // If the name is a simple identifier (by far the common case), or a // zero-argument selector, just return a reference to that identifier. if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) return Id->getName(); if (Name.isObjCZeroArgSelector()) if (IdentifierInfo *Id = Name.getObjCSelector().getIdentifierInfoForSlot(0)) return Id->getName(); Saved = Name.getAsString(); return Saved; }
bool TraverseFunctionDecl(FunctionDecl *f) { // Function name DeclarationName DeclName = f->getNameInfo().getName(); std::string FuncName = DeclName.getAsString(); const FunctionType * fntyp = f->getType()->getAs<FunctionType>(); if(!fntyp) return true; if(f->getStorageClass() == clang::SC_Static) { ImportError("cannot import static functions."); SetErrorReport(FuncName.c_str()); return true; } Obj typ; if(!GetFuncType(fntyp,&typ)) { SetErrorReport(FuncName.c_str()); return true; } std::string InternalName = FuncName; AsmLabelAttr * asmlabel = f->getAttr<AsmLabelAttr>(); if(asmlabel) { InternalName = asmlabel->getLabel(); #ifndef __linux__ //In OSX and Windows LLVM mangles assembler labels by adding a '\01' prefix InternalName.insert(InternalName.begin(), '\01'); #endif } CreateFunction(FuncName,InternalName,&typ); KeepFunctionLive(f);//make sure this function is live in codegen by creating a dummy reference to it (void) is to suppress unused warnings return true; }
///\brief This is the most important function of the class ASTImportSource /// since from here initiates the lookup and import part of the missing /// Decl(s) (Contexts). /// bool ASTImportSource::FindExternalVisibleDeclsByName( const DeclContext *childCurrentDeclContext, DeclarationName childDeclName) { assert(childCurrentDeclContext->hasExternalVisibleStorage() && "DeclContext has no visible decls in storage"); //Check if we have already found this declaration Name before DeclarationName parentDeclName; std::map<clang::DeclarationName, clang::DeclarationName>::iterator II = m_DeclName_map.find(childDeclName); if (II != m_DeclName_map.end()) { parentDeclName = II->second; } else { // Get the identifier info from the parent interpreter // for this Name. llvm::StringRef name(childDeclName.getAsString()); IdentifierTable &parentIdentifierTable = m_parent_Interp->getCI()->getASTContext().Idents; IdentifierInfo &parentIdentifierInfo = parentIdentifierTable.get(name); DeclarationName parentDeclNameTemp(&parentIdentifierInfo); parentDeclName = parentDeclNameTemp; } // Search in the map of the stored Decl Contexts for this // Decl Context. std::map<const clang::DeclContext *, clang::DeclContext *>::iterator I; if ((I = m_DeclContexts_map.find(childCurrentDeclContext)) != m_DeclContexts_map.end()) { // If childCurrentDeclContext was found before and is already in the map, // then do the lookup using the stored pointer. DeclContext *parentDeclContext = I->second; Decl *fromDeclContext = Decl::castFromDeclContext(parentDeclContext); ASTContext &from_ASTContext = fromDeclContext->getASTContext(); Decl *toDeclContext = Decl::castFromDeclContext(childCurrentDeclContext); ASTContext &to_ASTContext = toDeclContext->getASTContext(); DeclContext::lookup_result lookup_result = parentDeclContext->lookup(parentDeclName); // Check if we found this Name in the parent interpreter if (!lookup_result.empty()) { // Do the import if (Import(lookup_result, from_ASTContext, to_ASTContext, childCurrentDeclContext, childDeclName, parentDeclName)) return true; } } return false; }
bool VisitFunctionDecl(FunctionDecl *f) { // Only function definitions (with bodies), not declarations. Stmt *FuncBody = f->getBody(); // Type name as string QualType QT = f->getResultType(); string TypeStr = QT.getAsString(); // Function name DeclarationName DeclName = f->getNameInfo().getName(); string FuncName = DeclName.getAsString(); func_info fi; fi.name = FuncName; fi.return_type = TypeStr; unsigned nbp = f->getNumParams(); for (int i = 0; i < nbp; ++i) { //getTypeSourceInfo()->getType() and getOriginalType() is the final type. e.g. for size_t, the result may be unsigned int, but we need only size_t //fi.argv.push_back(f->getParamDecl(i)->getTypeSourceInfo()->getType().getAsString());//->getOriginalType().getAsString()); /* TypeLoc tl = f->getParamDecl(i)->getTypeSourceInfo()->getTypeLoc(); SourceLocation sl0 = tl.getBeginLoc(); SourceLocation sl1 = tl.getEndLoc(); const char* ptr0 = TheRewriter.getSourceMgr().getCharacterData(sl0); const char* ptr1 = TheRewriter.getSourceMgr().getCharacterData(sl1); */ fi.argv.push_back(trim(decl2str_without_var(f->getParamDecl(i), &TheRewriter.getSourceMgr()))); } mFuncInfo.push_back(fi); #if 0 if (f->hasBody()) { // Add comment before stringstream SSBefore; SSBefore << "// Begin function " << FuncName << " returning " << TypeStr << "\n"; SourceLocation ST = f->getSourceRange().getBegin(); TheRewriter.InsertText(ST, SSBefore.str(), true, true); // And after stringstream SSAfter; SSAfter << "\n// End function " << FuncName << "\n"; ST = FuncBody->getLocEnd().getLocWithOffset(1); TheRewriter.InsertText(ST, SSAfter.str(), true, true); } #endif return true; }
// 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); }
/// Build a new nested-name-specifier for "identifier::", as described /// by ActOnCXXNestedNameSpecifier. /// /// \param S Scope in which the nested-name-specifier occurs. /// \param IdInfo Parser information about an identifier in the /// nested-name-spec. /// \param EnteringContext If true, enter the context specified by the /// nested-name-specifier. /// \param SS Optional nested name specifier preceding the identifier. /// \param ScopeLookupResult Provides the result of name lookup within the /// scope of the nested-name-specifier that was computed at template /// definition time. /// \param ErrorRecoveryLookup Specifies if the method is called to improve /// error recovery and what kind of recovery is performed. /// \param IsCorrectedToColon If not null, suggestion of replace '::' -> ':' /// are allowed. The bool value pointed by this parameter is set to /// 'true' if the identifier is treated as if it was followed by ':', /// not '::'. /// \param OnlyNamespace If true, only considers namespaces in lookup. /// /// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in /// that it contains an extra parameter \p ScopeLookupResult, which provides /// the result of name lookup within the scope of the nested-name-specifier /// that was computed at template definition time. /// /// If ErrorRecoveryLookup is true, then this call is used to improve error /// recovery. This means that it should not emit diagnostics, it should /// just return true on failure. It also means it should only return a valid /// scope if it *knows* that the result is correct. It should not return in a /// dependent context, for example. Nor will it extend \p SS with the scope /// specifier. bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool EnteringContext, CXXScopeSpec &SS, NamedDecl *ScopeLookupResult, bool ErrorRecoveryLookup, bool *IsCorrectedToColon, bool OnlyNamespace) { if (IdInfo.Identifier->isEditorPlaceholder()) return true; LookupResult Found(*this, IdInfo.Identifier, IdInfo.IdentifierLoc, OnlyNamespace ? LookupNamespaceName : LookupNestedNameSpecifierName); QualType ObjectType = GetTypeFromParser(IdInfo.ObjectType); // Determine where to perform name lookup DeclContext *LookupCtx = nullptr; bool isDependent = false; if (IsCorrectedToColon) *IsCorrectedToColon = false; if (!ObjectType.isNull()) { // This nested-name-specifier occurs in a member access expression, e.g., // x->B::f, and we are looking into the type of the object. assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); LookupCtx = computeDeclContext(ObjectType); isDependent = ObjectType->isDependentType(); } else if (SS.isSet()) { // This nested-name-specifier occurs after another nested-name-specifier, // so look into the context associated with the prior nested-name-specifier. LookupCtx = computeDeclContext(SS, EnteringContext); isDependent = isDependentScopeSpecifier(SS); Found.setContextRange(SS.getRange()); } bool ObjectTypeSearchedInScope = false; if (LookupCtx) { // Perform "qualified" name lookup into the declaration context we // computed, which is either the type of the base of a member access // expression or the declaration context associated with a prior // nested-name-specifier. // The declaration context must be complete. if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS, LookupCtx)) return true; LookupQualifiedName(Found, LookupCtx); if (!ObjectType.isNull() && Found.empty()) { // C++ [basic.lookup.classref]p4: // If the id-expression in a class member access is a qualified-id of // the form // // class-name-or-namespace-name::... // // the class-name-or-namespace-name following the . or -> operator is // looked up both in the context of the entire postfix-expression and in // the scope of the class of the object expression. If the name is found // only in the scope of the class of the object expression, the name // shall refer to a class-name. If the name is found only in the // context of the entire postfix-expression, the name shall refer to a // class-name or namespace-name. [...] // // Qualified name lookup into a class will not find a namespace-name, // so we do not need to diagnose that case specifically. However, // this qualified name lookup may find nothing. In that case, perform // unqualified name lookup in the given scope (if available) or // reconstruct the result from when name lookup was performed at template // definition time. if (S) LookupName(Found, S); else if (ScopeLookupResult) Found.addDecl(ScopeLookupResult); ObjectTypeSearchedInScope = true; } } else if (!isDependent) { // Perform unqualified name lookup in the current scope. LookupName(Found, S); } if (Found.isAmbiguous()) return true; // If we performed lookup into a dependent context and did not find anything, // that's fine: just build a dependent nested-name-specifier. if (Found.empty() && isDependent && !(LookupCtx && LookupCtx->isRecord() && (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() || !cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) { // Don't speculate if we're just trying to improve error recovery. if (ErrorRecoveryLookup) return true; // We were not able to compute the declaration context for a dependent // base object type or prior nested-name-specifier, so this // nested-name-specifier refers to an unknown specialization. Just build // a dependent nested-name-specifier. SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; } if (Found.empty() && !ErrorRecoveryLookup) { // If identifier is not found as class-name-or-namespace-name, but is found // as other entity, don't look for typos. LookupResult R(*this, Found.getLookupNameInfo(), LookupOrdinaryName); if (LookupCtx) LookupQualifiedName(R, LookupCtx); else if (S && !isDependent) LookupName(R, S); if (!R.empty()) { // Don't diagnose problems with this speculative lookup. R.suppressDiagnostics(); // The identifier is found in ordinary lookup. If correction to colon is // allowed, suggest replacement to ':'. if (IsCorrectedToColon) { *IsCorrectedToColon = true; Diag(IdInfo.CCLoc, diag::err_nested_name_spec_is_not_class) << IdInfo.Identifier << getLangOpts().CPlusPlus << FixItHint::CreateReplacement(IdInfo.CCLoc, ":"); if (NamedDecl *ND = R.getAsSingle<NamedDecl>()) Diag(ND->getLocation(), diag::note_declared_at); return true; } // Replacement '::' -> ':' is not allowed, just issue respective error. Diag(R.getNameLoc(), OnlyNamespace ? unsigned(diag::err_expected_namespace_name) : unsigned(diag::err_expected_class_or_namespace)) << IdInfo.Identifier << getLangOpts().CPlusPlus; if (NamedDecl *ND = R.getAsSingle<NamedDecl>()) Diag(ND->getLocation(), diag::note_entity_declared_at) << IdInfo.Identifier; return true; } } if (Found.empty() && !ErrorRecoveryLookup && !getLangOpts().MSVCCompat) { // We haven't found anything, and we're not recovering from a // different kind of error, so look for typos. DeclarationName Name = Found.getLookupName(); Found.clear(); NestedNameSpecifierValidatorCCC CCC(*this); if (TypoCorrection Corrected = CorrectTypo( Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, CCC, CTK_ErrorRecovery, LookupCtx, EnteringContext)) { if (LookupCtx) { bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && Name.getAsString() == Corrected.getAsString(getLangOpts()); if (DroppedSpecifier) SS.clear(); diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest) << Name << LookupCtx << DroppedSpecifier << SS.getRange()); } else diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest) << Name); if (Corrected.getCorrectionSpecifier()) SS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), SourceRange(Found.getNameLoc())); if (NamedDecl *ND = Corrected.getFoundDecl()) Found.addDecl(ND); Found.setLookupName(Corrected.getCorrection()); } else { Found.setLookupName(IdInfo.Identifier); } } NamedDecl *SD = Found.isSingleResult() ? Found.getRepresentativeDecl() : nullptr; bool IsExtension = false; bool AcceptSpec = isAcceptableNestedNameSpecifier(SD, &IsExtension); if (!AcceptSpec && IsExtension) { AcceptSpec = true; Diag(IdInfo.IdentifierLoc, diag::ext_nested_name_spec_is_enum); } if (AcceptSpec) { if (!ObjectType.isNull() && !ObjectTypeSearchedInScope && !getLangOpts().CPlusPlus11) { // C++03 [basic.lookup.classref]p4: // [...] If the name is found in both contexts, the // class-name-or-namespace-name shall refer to the same entity. // // We already found the name in the scope of the object. Now, look // into the current scope (the scope of the postfix-expression) to // see if we can find the same name there. As above, if there is no // scope, reconstruct the result from the template instantiation itself. // // Note that C++11 does *not* perform this redundant lookup. NamedDecl *OuterDecl; if (S) { LookupResult FoundOuter(*this, IdInfo.Identifier, IdInfo.IdentifierLoc, LookupNestedNameSpecifierName); LookupName(FoundOuter, S); OuterDecl = FoundOuter.getAsSingle<NamedDecl>(); } else OuterDecl = ScopeLookupResult; if (isAcceptableNestedNameSpecifier(OuterDecl) && OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() && (!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) || !Context.hasSameType( Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)), Context.getTypeDeclType(cast<TypeDecl>(SD))))) { if (ErrorRecoveryLookup) return true; Diag(IdInfo.IdentifierLoc, diag::err_nested_name_member_ref_lookup_ambiguous) << IdInfo.Identifier; Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type) << ObjectType; Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope); // Fall through so that we'll pick the name we found in the object // type, since that's probably what the user wanted anyway. } } if (auto *TD = dyn_cast_or_null<TypedefNameDecl>(SD)) MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); // If we're just performing this lookup for error-recovery purposes, // don't extend the nested-name-specifier. Just return now. if (ErrorRecoveryLookup) return false; // The use of a nested name specifier may trigger deprecation warnings. DiagnoseUseOfDecl(SD, IdInfo.CCLoc); if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) { SS.Extend(Context, Namespace, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; } if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) { SS.Extend(Context, Alias, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; } QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD->getUnderlyingDecl())); TypeLocBuilder TLB; if (isa<InjectedClassNameType>(T)) { InjectedClassNameTypeLoc InjectedTL = TLB.push<InjectedClassNameTypeLoc>(T); InjectedTL.setNameLoc(IdInfo.IdentifierLoc); } else if (isa<RecordType>(T)) { RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T); RecordTL.setNameLoc(IdInfo.IdentifierLoc); } else if (isa<TypedefType>(T)) { TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T); TypedefTL.setNameLoc(IdInfo.IdentifierLoc); } else if (isa<EnumType>(T)) { EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T); EnumTL.setNameLoc(IdInfo.IdentifierLoc); } else if (isa<TemplateTypeParmType>(T)) { TemplateTypeParmTypeLoc TemplateTypeTL = TLB.push<TemplateTypeParmTypeLoc>(T); TemplateTypeTL.setNameLoc(IdInfo.IdentifierLoc); } else if (isa<UnresolvedUsingType>(T)) { UnresolvedUsingTypeLoc UnresolvedTL = TLB.push<UnresolvedUsingTypeLoc>(T); UnresolvedTL.setNameLoc(IdInfo.IdentifierLoc); } else if (isa<SubstTemplateTypeParmType>(T)) { SubstTemplateTypeParmTypeLoc TL = TLB.push<SubstTemplateTypeParmTypeLoc>(T); TL.setNameLoc(IdInfo.IdentifierLoc); } else if (isa<SubstTemplateTypeParmPackType>(T)) { SubstTemplateTypeParmPackTypeLoc TL = TLB.push<SubstTemplateTypeParmPackTypeLoc>(T); TL.setNameLoc(IdInfo.IdentifierLoc); } else { llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier"); } if (T->isEnumeralType()) Diag(IdInfo.IdentifierLoc, diag::warn_cxx98_compat_enum_nested_name_spec); SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), IdInfo.CCLoc); return false; } // Otherwise, we have an error case. If we don't want diagnostics, just // return an error now. if (ErrorRecoveryLookup) return true; // If we didn't find anything during our lookup, try again with // ordinary name lookup, which can help us produce better error // messages. if (Found.empty()) { Found.clear(LookupOrdinaryName); LookupName(Found, S); } // In Microsoft mode, if we are within a templated function and we can't // resolve Identifier, then extend the SS with Identifier. This will have // the effect of resolving Identifier during template instantiation. // The goal is to be able to resolve a function call whose // nested-name-specifier is located inside a dependent base class. // Example: // // class C { // public: // static void foo2() { } // }; // template <class T> class A { public: typedef C D; }; // // template <class T> class B : public A<T> { // public: // void foo() { D::foo2(); } // }; if (getLangOpts().MSVCCompat) { DeclContext *DC = LookupCtx ? LookupCtx : CurContext; if (DC->isDependentContext() && DC->isFunctionOrMethod()) { CXXRecordDecl *ContainingClass = dyn_cast<CXXRecordDecl>(DC->getParent()); if (ContainingClass && ContainingClass->hasAnyDependentBases()) { Diag(IdInfo.IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << IdInfo.Identifier << ContainingClass; SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; } } } if (!Found.empty()) { if (TypeDecl *TD = Found.getAsSingle<TypeDecl>()) Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) << Context.getTypeDeclType(TD) << getLangOpts().CPlusPlus; else { Diag(IdInfo.IdentifierLoc, diag::err_expected_class_or_namespace) << IdInfo.Identifier << getLangOpts().CPlusPlus; if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) Diag(ND->getLocation(), diag::note_entity_declared_at) << IdInfo.Identifier; } } else if (SS.isSet()) Diag(IdInfo.IdentifierLoc, diag::err_no_member) << IdInfo.Identifier << LookupCtx << SS.getRange(); else Diag(IdInfo.IdentifierLoc, diag::err_undeclared_var_use) << IdInfo.Identifier; return true; }
void clang::FormatASTNodeDiagnosticArgument(Diagnostic::ArgumentKind Kind, intptr_t Val, const char *Modifier, unsigned ModLen, const char *Argument, unsigned ArgLen, const Diagnostic::ArgumentValue *PrevArgs, unsigned NumPrevArgs, llvm::SmallVectorImpl<char> &Output, void *Cookie) { ASTContext &Context = *static_cast<ASTContext*>(Cookie); std::string S; bool NeedQuotes = true; switch (Kind) { default: assert(0 && "unknown ArgumentKind"); case Diagnostic::ak_qualtype: { assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for QualType argument"); QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs); NeedQuotes = false; break; } case Diagnostic::ak_declarationname: { DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); S = N.getAsString(); if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0) S = '+' + S; else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) && ArgLen==0) S = '-' + S; else assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for DeclarationName argument"); break; } case Diagnostic::ak_nameddecl: { bool Qualified; if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0) Qualified = true; else { assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for NamedDecl* argument"); Qualified = false; } reinterpret_cast<NamedDecl*>(Val)-> getNameForDiagnostic(S, Context.PrintingPolicy, Qualified); break; } case Diagnostic::ak_nestednamespec: { llvm::raw_string_ostream OS(S); reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS, Context.PrintingPolicy); NeedQuotes = false; break; } case Diagnostic::ak_declcontext: { DeclContext *DC = reinterpret_cast<DeclContext *> (Val); assert(DC && "Should never have a null declaration context"); if (DC->isTranslationUnit()) { // FIXME: Get these strings from some localized place if (Context.getLangOptions().CPlusPlus) S = "the global namespace"; else S = "the global scope"; } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type), PrevArgs, NumPrevArgs); } else { // FIXME: Get these strings from some localized place NamedDecl *ND = cast<NamedDecl>(DC); if (isa<NamespaceDecl>(ND)) S += "namespace "; else if (isa<ObjCMethodDecl>(ND)) S += "method "; else if (isa<FunctionDecl>(ND)) S += "function "; S += "'"; ND->getNameForDiagnostic(S, Context.PrintingPolicy, true); S += "'"; } NeedQuotes = false; break; } } if (NeedQuotes) Output.push_back('\''); Output.append(S.begin(), S.end()); if (NeedQuotes) Output.push_back('\''); }
bool VisitFunctionDecl(FunctionDecl *f) { // Only function definitions (with bodies), not declarations. if (f->hasBody()) { Stmt *FuncBody = f->getBody(); // Type name as string QualType QT = f->getReturnType(); std::string TypeStr = QT.getAsString(); // Function name DeclarationName DeclName = f->getNameInfo().getName(); std::string FuncName = DeclName.getAsString(); // Add comment before std::stringstream SSBefore; SSBefore << "// Begin function " << FuncName << " returning " << TypeStr << "\n"; SourceLocation ST = f->getSourceRange().getBegin(); TheRewriter.InsertText(ST, SSBefore.str(), true, true); // And after std::stringstream SSAfter; SSAfter << "\n// End function " << FuncName; ST = FuncBody->getLocEnd().getLocWithOffset(1); TheRewriter.InsertText(ST, SSAfter.str(), true, true); int forCounter=0; Stmt::child_iterator CI, CE = FuncBody->child_end(); for (CI = FuncBody->child_begin(); CI != CE; ++CI) { if (*CI != 0) { if (isa<ForStmt>(*CI)) { forCounter++; std::stringstream MarkerBefore; std::stringstream MarkerAfter; MarkerBefore<<"\nMCPROF_ZONE_ENTER(" << forCounter << ");\n"; MarkerAfter<<"\nMCPROF_ZONE_EXIT(" << forCounter << ");\n"; ForStmt *For = cast<ForStmt>(*CI); SourceLocation ST = For->getLocStart(); TheRewriter.InsertText(ST, MarkerBefore.str(), true, false); Stmt *ForBody = For->getBody(); SourceLocation END = ForBody->getLocEnd(); int offset = Lexer::MeasureTokenLength(END, TheRewriter.getSourceMgr(), TheRewriter.getLangOpts()) + 1; SourceLocation END1 = END.getLocWithOffset(offset); TheRewriter.InsertText(END1, MarkerAfter.str(), true, false); // llvm::errs() << " Detected for loop number " << forCounter // << " in function " << FuncName << "\n"; // InstrumentStmt(ForBody); // Stmt *ForBody = CI->getBody(); // SourceLocation ST = CI->getLocStart(); // char *b = sourceManager->getCharacterData(_b) // llvm::errs() << ST << " is location \n"; } } } } return true; }
/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an /// objective C interface. This is a property reference expression. ExprResult Sema:: HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Expr *BaseExpr, DeclarationName MemberName, SourceLocation MemberLoc, SourceLocation SuperLoc, QualType SuperType, bool Super) { const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); ObjCInterfaceDecl *IFace = IFaceT->getDecl(); IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); if (IFace->isForwardDecl()) { Diag(MemberLoc, diag::err_property_not_found_forward_class) << MemberName << QualType(OPT, 0); Diag(IFace->getLocation(), diag::note_forward_class); return ExprError(); } // Search for a declared property first. if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); QualType ResTy = PD->getType(); Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) ResTy = Getter->getResultType(); if (Super) return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, VK_LValue, OK_ObjCProperty, MemberLoc, SuperLoc, SuperType)); else return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, VK_LValue, OK_ObjCProperty, MemberLoc, BaseExpr)); } // Check protocols on qualified interfaces. for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), E = OPT->qual_end(); I != E; ++I) if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); if (Super) return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), VK_LValue, OK_ObjCProperty, MemberLoc, SuperLoc, SuperType)); else return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), VK_LValue, OK_ObjCProperty, MemberLoc, BaseExpr)); } // If that failed, look for an "implicit" property by seeing if the nullary // selector is implemented. // FIXME: The logic for looking up nullary and unary selectors should be // shared with the code in ActOnInstanceMessage. Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); // May be founf in property's qualified list. if (!Getter) Getter = LookupMethodInQualifiedType(Sel, OPT, true); // If this reference is in an @implementation, check for 'private' methods. if (!Getter) Getter = IFace->lookupPrivateMethod(Sel); // Look through local category implementations associated with the class. if (!Getter) Getter = IFace->getCategoryInstanceMethod(Sel); if (Getter) { // Check if we can reference this property. if (DiagnoseUseOfDecl(Getter, MemberLoc)) return ExprError(); } // If we found a getter then this may be a valid dot-reference, we // will look for the matching setter, in case it is needed. Selector SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(), PP.getSelectorTable(), Member); ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); // May be founf in property's qualified list. if (!Setter) Setter = LookupMethodInQualifiedType(SetterSel, OPT, true); if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. Setter = IFace->lookupPrivateMethod(SetterSel); } // Look through local category implementations associated with the class. if (!Setter) Setter = IFace->getCategoryInstanceMethod(SetterSel); if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) return ExprError(); if (Getter || Setter) { QualType PType; if (Getter) PType = Getter->getSendResultType(); else { ParmVarDecl *ArgDecl = *Setter->param_begin(); PType = ArgDecl->getType(); } ExprValueKind VK = VK_LValue; ExprObjectKind OK = OK_ObjCProperty; if (!getLangOptions().CPlusPlus && !PType.hasQualifiers() && PType->isVoidType()) VK = VK_RValue, OK = OK_Ordinary; if (Super) return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, PType, VK, OK, MemberLoc, SuperLoc, SuperType)); else return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, PType, VK, OK, MemberLoc, BaseExpr)); } // Attempt to correct for typos in property names. LookupResult Res(*this, MemberName, MemberLoc, LookupOrdinaryName); if (CorrectTypo(Res, 0, 0, IFace, false, CTC_NoKeywords, OPT) && Res.getAsSingle<ObjCPropertyDecl>()) { DeclarationName TypoResult = Res.getLookupName(); Diag(MemberLoc, diag::err_property_not_found_suggest) << MemberName << QualType(OPT, 0) << TypoResult << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString()); ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>(); Diag(Property->getLocation(), diag::note_previous_decl) << Property->getDeclName(); return HandleExprPropertyRefExpr(OPT, BaseExpr, TypoResult, MemberLoc, SuperLoc, SuperType, Super); } ObjCInterfaceDecl *ClassDeclared; if (ObjCIvarDecl *Ivar = IFace->lookupInstanceVariable(Member, ClassDeclared)) { QualType T = Ivar->getType(); if (const ObjCObjectPointerType * OBJPT = T->getAsObjCInterfacePointerType()) { const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); if (ObjCInterfaceDecl *IFace = IFaceT->getDecl()) if (IFace->isForwardDecl()) { Diag(MemberLoc, diag::err_property_not_as_forward_class) << MemberName << IFace; Diag(IFace->getLocation(), diag::note_forward_class); return ExprError(); } } } Diag(MemberLoc, diag::err_property_not_found) << MemberName << QualType(OPT, 0); if (Setter) Diag(Setter->getLocation(), diag::note_getter_unavailable) << MemberName << BaseExpr->getSourceRange(); return ExprError(); }
static std::string getPrintableNameForEntity(DeclarationName Entity) { if (Entity) return Entity.getAsString(); return "type name"; }
/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an /// objective C interface. This is a property reference expression. Action::OwningExprResult Sema:: HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Expr *BaseExpr, DeclarationName MemberName, SourceLocation MemberLoc) { const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); ObjCInterfaceDecl *IFace = IFaceT->getDecl(); IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); // Search for a declared property first. if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); QualType ResTy = PD->getType(); Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) ResTy = Getter->getSendResultType(); return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, MemberLoc, BaseExpr)); } // Check protocols on qualified interfaces. for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), E = OPT->qual_end(); I != E; ++I) if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr)); } // If that failed, look for an "implicit" property by seeing if the nullary // selector is implemented. // FIXME: The logic for looking up nullary and unary selectors should be // shared with the code in ActOnInstanceMessage. Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); // If this reference is in an @implementation, check for 'private' methods. if (!Getter) Getter = IFace->lookupPrivateInstanceMethod(Sel); // Look through local category implementations associated with the class. if (!Getter) Getter = IFace->getCategoryInstanceMethod(Sel); if (Getter) { // Check if we can reference this property. if (DiagnoseUseOfDecl(Getter, MemberLoc)) return ExprError(); } // If we found a getter then this may be a valid dot-reference, we // will look for the matching setter, in case it is needed. Selector SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(), PP.getSelectorTable(), Member); ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. Setter = IFace->lookupPrivateInstanceMethod(SetterSel); } // Look through local category implementations associated with the class. if (!Setter) Setter = IFace->getCategoryInstanceMethod(SetterSel); if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) return ExprError(); if (Getter) { QualType PType; PType = Getter->getSendResultType(); return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType, Setter, MemberLoc, BaseExpr)); } // Attempt to correct for typos in property names. LookupResult Res(*this, MemberName, MemberLoc, LookupOrdinaryName); if (CorrectTypo(Res, 0, 0, IFace, false, CTC_NoKeywords, OPT) && Res.getAsSingle<ObjCPropertyDecl>()) { DeclarationName TypoResult = Res.getLookupName(); Diag(MemberLoc, diag::err_property_not_found_suggest) << MemberName << QualType(OPT, 0) << TypoResult << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString()); ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>(); Diag(Property->getLocation(), diag::note_previous_decl) << Property->getDeclName(); return HandleExprPropertyRefExpr(OPT, BaseExpr, TypoResult, MemberLoc); } Diag(MemberLoc, diag::err_property_not_found) << MemberName << QualType(OPT, 0); if (Setter && !Getter) Diag(Setter->getLocation(), diag::note_getter_unavailable) << MemberName << BaseExpr->getSourceRange(); return ExprError(); }
void clang::FormatASTNodeDiagnosticArgument( DiagnosticsEngine::ArgumentKind Kind, intptr_t Val, const char *Modifier, unsigned ModLen, const char *Argument, unsigned ArgLen, const DiagnosticsEngine::ArgumentValue *PrevArgs, unsigned NumPrevArgs, SmallVectorImpl<char> &Output, void *Cookie, ArrayRef<intptr_t> QualTypeVals) { ASTContext &Context = *static_cast<ASTContext*>(Cookie); std::string S; bool NeedQuotes = true; switch (Kind) { default: llvm_unreachable("unknown ArgumentKind"); case DiagnosticsEngine::ak_qualtype_pair: { TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val); QualType FromType = QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.FromType)); QualType ToType = QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.ToType)); if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree, TDT.PrintFromType, TDT.ElideType, TDT.ShowColors, S)) { NeedQuotes = !TDT.PrintTree; TDT.TemplateDiffUsed = true; break; } // Don't fall-back during tree printing. The caller will handle // this case. if (TDT.PrintTree) return; // Attempting to do a templete diff on non-templates. Set the variables // and continue with regular type printing of the appropriate type. Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType; ModLen = 0; ArgLen = 0; // Fall through } case DiagnosticsEngine::ak_qualtype: { assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for QualType argument"); QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs, QualTypeVals); NeedQuotes = false; break; } case DiagnosticsEngine::ak_declarationname: { DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); S = N.getAsString(); if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0) S = '+' + S; else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) && ArgLen==0) S = '-' + S; else assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for DeclarationName argument"); break; } case DiagnosticsEngine::ak_nameddecl: { bool Qualified; if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0) Qualified = true; else { assert(ModLen == 0 && ArgLen == 0 && "Invalid modifier for NamedDecl* argument"); Qualified = false; } const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val); ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), Qualified); break; } case DiagnosticsEngine::ak_nestednamespec: { llvm::raw_string_ostream OS(S); reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS, Context.getPrintingPolicy()); NeedQuotes = false; break; } case DiagnosticsEngine::ak_declcontext: { DeclContext *DC = reinterpret_cast<DeclContext *> (Val); assert(DC && "Should never have a null declaration context"); if (DC->isTranslationUnit()) { // FIXME: Get these strings from some localized place if (Context.getLangOpts().CPlusPlus) S = "the global namespace"; else S = "the global scope"; } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type), PrevArgs, NumPrevArgs, QualTypeVals); } else { // FIXME: Get these strings from some localized place NamedDecl *ND = cast<NamedDecl>(DC); if (isa<NamespaceDecl>(ND)) S += "namespace "; else if (isa<ObjCMethodDecl>(ND)) S += "method "; else if (isa<FunctionDecl>(ND)) S += "function "; S += "'"; ND->getNameForDiagnostic(S, Context.getPrintingPolicy(), true); S += "'"; } NeedQuotes = false; break; } } if (NeedQuotes) Output.push_back('\''); Output.append(S.begin(), S.end()); if (NeedQuotes) Output.push_back('\''); }