/// LookupBuiltin - Lookup for built-in functions 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 defn object for the builtin // now, injecting it into system scope, and return it. if (NameKind == Sema::LookupOrdinaryName) { IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo(); if (II) { // If this is a builtin on this (or all) targets, create the defn. if (unsigned BuiltinID = II->getBuiltinID()) { if (NamedDefn *D = S.LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, S.BaseWorkspace, /*R.isForRedeclaration()*/false, R.getNameLoc())) { R.addDefn(D); return true; } //FIXME yabin // should i deal with this situation in gmat? // if (R.isForRedeclaration()) { // // If we're redeclaring this function anyway, forget that // // this was a builtin at all. // S.Context.BuiltinInfo.ForgetBuiltin(BuiltinID, // S.Context.Idents); // } return false; } } } return false; }
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; }
/// Checks access to all the declarations in the given result set. void Sema::CheckLookupAccess(const LookupResult &R) { assert(getLangOptions().AccessControl && "performing access check without access control"); assert(R.getNamingClass() && "performing access check without naming class"); for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { if (I.getAccess() != AS_public) { AccessTarget Entity(Context, AccessedEntity::Member, R.getNamingClass(), I.getPair(), R.getBaseObjectType()); Entity.setDiag(diag::err_access); CheckAccess(*this, R.getNameLoc(), Entity); } } }
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; }
// Returns true on failure. static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, //SourceRange BaseRange, const StructType *STy, SourceLocation OpLoc) { StructTypeDecl *SDecl = STy->getDecl(); DeclContext *DC = SDecl; // The record definition is complete, now look up the member. SemaRef.LookupQualifiedName(R, DC); if (!R.empty()) return false; #if 0 // We didn't find anything with the given name, so try to correct // for typos. DeclarationName Name = R.getLookupName(); RecordMemberExprValidatorCCC Validator; TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), NULL, &SS, Validator, DC); R.clear(); if (NamedDecl *ND = Corrected.getCorrectionDecl()) { std::string CorrectedStr( Corrected.getAsString(SemaRef.getLangOpts())); std::string CorrectedQuotedStr( Corrected.getQuoted(SemaRef.getLangOpts())); R.setLookupName(Corrected.getCorrection()); R.addDecl(ND); SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest) << Name << DC << CorrectedQuotedStr << SS.getRange() << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), CorrectedStr); SemaRef.Diag(ND->getLocation(), diag::note_previous_decl) << ND->getDeclName(); } #endif // FIXME: Is this right? (also in clang) return false; }
/// Look up the given member of the given non-type-dependent /// expression. This can return in one of two ways: /// * If it returns a sentinel null-but-valid result, the caller will /// assume that lookup was performed and the results written into /// the provided structure. It will take over from there. /// * Otherwise, the returned expression will be produced in place of /// an ordinary member expression. Action::OwningExprResult Sema::LookupMemberExpr(LookupResult &R, Expr &BaseExpr, SourceLocation OpLoc) { const Type *BaseType = BaseExpr.getType(); assert(BaseType); SourceLocation MemberLoc = R.getNameLoc(); #if 0 DeclarationName MemberName = R.getLookupName(); // For later type-checking purposes, turn arrow accesses into dot // accesses. The only access type we support that doesn't follow // the C equivalence "a->b === (*a).b" is ObjC property accesses, // and those never use arrows, so this is unaffected. if (IsArrow) { if (const PointerType *Ptr = BaseType->getAs<PointerType>()) BaseType = Ptr->getPointeeType(); else if (BaseType->isRecordType()) { // Recover from arrow accesses to records, e.g.: // struct MyRecord foo; // foo->bar // This is actually well-formed in C++ if MyRecord has an // overloaded operator->, but that should have been dealt with // by now. Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() << FixItHint::CreateReplacement(OpLoc, "."); IsArrow = false; } else if (BaseType->isFunctionType()) { goto fail; } else { Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) << BaseType << BaseExpr.get()->getSourceRange(); return ExprError(); } } #endif // spec#Selector: "If x is a pointer to a struct, x.y is shorthand for (*x).y" if (const PointerType *P = dyn_cast<PointerType>(BaseType)) BaseType = P->getPointeeType(); // Handle field access to simple records. if (const StructType *STy = BaseType->getAs<StructType>()) { if (LookupMemberExprInRecord(*this, R, //BaseExpr.get()->getSourceRange(), STy, OpLoc)) return ExprError(); // Returning valid-but-null is how we indicate to the caller that // the lookup result was filled in. return Owned((Expr *)0); } #if 0 // Failure cases. fail: // If the user is trying to apply . to a function name, it's probably // because they forgot parentheses to call that function. if (tryToRecoverWithCall(BaseExpr, PDiag(diag::err_member_reference_needs_call), /*complain*/ false, IsArrow ? &isPointerToRecordType : &isRecordType)) { if (BaseExpr.isInvalid()) return ExprError(); BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc); } #endif Diag(OpLoc, diag::typecheck_field_reference_struct) //<< BaseType << BaseExpr.get()->getSourceRange() << MemberLoc; << BaseType << SourceRange(MemberLoc, MemberLoc); return ExprError(); }
Action::OwningExprResult Sema::BuildMemberReferenceExpr(Expr *BaseExpr, const Type *BaseExprType, SourceLocation OpLoc, LookupResult &R) { const Type* BaseType = BaseExprType; if (const PointerType *P = dyn_cast<PointerType>(BaseType)) BaseType = P->getPointeeType(); //R.setBaseObjectType(BaseType); //const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); //DeclarationName MemberName = MemberNameInfo.getName(); //SourceLocation MemberLoc = MemberNameInfo.getLoc(); IdentifierInfo *II = R.getLookupName(); if (R.isAmbiguous()) return ExprError(); if (R.empty()) { // FIXME: make sure this prints the '*' for pointer-to-struct types (?) //DeclContext *DC = BaseType->getAs<StructType>()->getDecl(); // FIXME: clang prints DC instead of BaseExprType here. Don't do that, // else we don't print struct names right. However, make sure ParenTypes // get desugared once they exist. Diag(R.getNameLoc(), diag::no_field) << II << BaseExprType; //Diag(R.getNameLoc(), diag::err_no_member) //<< MemberName << DC //<< (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); return ExprError(); } assert(R.isSingleResult()); NamedDecl *MemberDecl = R.getFoundDecl(); #if 0 DeclAccessPair FoundDecl = R.begin().getPair(); // If the decl being referenced had an error, return an error for this // sub-expr without emitting another error, in order to avoid cascading // error cases. if (MemberDecl->isInvalidDecl()) return ExprError(); bool ShouldCheckUse = true; if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) { // Don't diagnose the use of a virtual member function unless it's // explicitly qualified. if (MD->isVirtual()) ShouldCheckUse = false; } // Check the use of this member. if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) { Owned(BaseExpr); return ExprError(); } #endif if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) { //return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, //FD, FoundDecl, MemberNameInfo); return Owned(BuildMemberExpr(*this, Context, BaseExpr, FD, R.getNameLoc(), FD->getType())); } #if 0 if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) // We may have found a field within an anonymous union or struct // (C++ [class.union]). return BuildAnonymousStructUnionMemberReference(MemberLoc, FD, BaseExpr, OpLoc); if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, Var, FoundDecl, MemberNameInfo, Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary)); } if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) { ExprValueKind valueKind; QualType type; if (MemberFn->isInstance()) { valueKind = VK_RValue; type = Context.BoundMemberTy; } else { valueKind = VK_LValue; type = MemberFn->getType(); } return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, MemberFn, FoundDecl, MemberNameInfo, type, valueKind, OK_Ordinary)); } assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, Enum, FoundDecl, MemberNameInfo, Enum->getType(), VK_RValue, OK_Ordinary)); } Owned(BaseExpr); // We found something that we didn't expect. Complain. if (isa<TypeDecl>(MemberDecl)) Diag(MemberLoc, diag::err_typecheck_member_reference_type) << MemberName << BaseType << int(IsArrow); else Diag(MemberLoc, diag::err_typecheck_member_reference_unknown) << MemberName << BaseType << int(IsArrow); Diag(MemberDecl->getLocation(), diag::note_member_declared_here) << MemberName; R.suppressDiagnostics(); #endif return ExprError(); }