bool DynamicIDHandler::LookupUnqualified(LookupResult& R, Scope* S) { if (!IsDynamicLookup(R, S)) return false; if (Callbacks && Callbacks->isEnabled()) { return Callbacks->LookupObject(R, S); } DeclarationName Name = R.getLookupName(); IdentifierInfo* II = Name.getAsIdentifierInfo(); SourceLocation Loc = R.getNameLoc(); VarDecl* Result = VarDecl::Create(m_Context, R.getSema().getFunctionLevelDeclContext(), Loc, Loc, II, m_Context.DependentTy, /*TypeSourceInfo*/0, SC_None, SC_None); if (Result) { R.addDecl(Result); // Say that we can handle the situation. Clang should try to recover return true; } // We cannot handle the situation. Give up return false; }
bool SymbolResolverCallback::LookupObject(LookupResult& R, Scope* S) { if (!ShouldResolveAtRuntime(R, S)) return false; if (m_IsRuntime) { // We are currently parsing an EvaluateT() expression if (!m_Resolve) return false; // Only for demo resolve all unknown objects to cling::test::Tester if (!m_TesterDecl) { clang::Sema& SemaR = m_Interpreter->getSema(); clang::NamespaceDecl* NSD = utils::Lookup::Namespace(&SemaR, "cling"); NSD = utils::Lookup::Namespace(&SemaR, "test", NSD); m_TesterDecl = utils::Lookup::Named(&SemaR, "Tester", NSD); } assert (m_TesterDecl && "Tester not found!"); R.addDecl(m_TesterDecl); return true; // Tell clang to continue. } // We are currently NOT parsing an EvaluateT() expression. // Escape the expression into an EvaluateT() expression. ASTContext& C = R.getSema().getASTContext(); DeclContext* DC = 0; // For DeclContext-less scopes like if (dyn_expr) {} while (!DC) { DC = static_cast<DeclContext*>(S->getEntity()); S = S->getParent(); } DeclarationName Name = R.getLookupName(); IdentifierInfo* II = Name.getAsIdentifierInfo(); SourceLocation Loc = R.getNameLoc(); VarDecl* Res = VarDecl::Create(C, DC, Loc, Loc, II, C.DependentTy, /*TypeSourceInfo*/0, SC_None); // Annotate the decl to give a hint in cling. FIXME: Current implementation // is a gross hack, because TClingCallbacks shouldn't know about // EvaluateTSynthesizer at all! SourceRange invalidRange; Res->addAttr(new (C) AnnotateAttr(invalidRange, C, "__ResolveAtRuntime", 0)); R.addDecl(Res); DC->addDecl(Res); // Say that we can handle the situation. Clang should try to recover return true; }
bool SymbolResolverCallback::ShouldResolveAtRuntime(LookupResult& R, Scope* S) { if (R.getLookupKind() != Sema::LookupOrdinaryName) return false; if (R.isForRedeclaration()) return false; if (!R.empty()) return false; // FIXME: Figure out better way to handle: // C++ [basic.lookup.classref]p1: // In a class member access expression (5.2.5), if the . or -> token is // immediately followed by an identifier followed by a <, the // identifier must be looked up to determine whether the < is the // beginning of a template argument list (14.2) or a less-than operator. // The identifier is first looked up in the class of the object // expression. If the identifier is not found, it is then looked up in // the context of the entire postfix-expression and shall name a class // or function template. // // We want to ignore object(.|->)member<template> if (R.getSema().PP.LookAhead(0).getKind() == tok::less) // TODO: check for . or -> in the cached token stream return false; for (Scope* DepScope = S; DepScope; DepScope = DepScope->getParent()) { if (DeclContext* Ctx = static_cast<DeclContext*>(DepScope->getEntity())) { if (!Ctx->isDependentContext()) // For now we support only the prompt. if (isa<FunctionDecl>(Ctx)) return true; } } return false; }