bool CoroutineStmtBuilder::makeOnFallthrough() { assert(!IsPromiseDependentType && "cannot make statement while the promise type is dependent"); // [dcl.fct.def.coroutine]/4 // The unqualified-ids 'return_void' and 'return_value' are looked up in // the scope of class P. If both are found, the program is ill-formed. bool HasRVoid, HasRValue; LookupResult LRVoid = lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid); LookupResult LRValue = lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue); StmtResult Fallthrough; if (HasRVoid && HasRValue) { // FIXME Improve this diagnostic S.Diag(FD.getLocation(), diag::err_coroutine_promise_incompatible_return_functions) << PromiseRecordDecl; S.Diag(LRVoid.getRepresentativeDecl()->getLocation(), diag::note_member_first_declared_here) << LRVoid.getLookupName(); S.Diag(LRValue.getRepresentativeDecl()->getLocation(), diag::note_member_first_declared_here) << LRValue.getLookupName(); return false; } else if (!HasRVoid && !HasRValue) { // FIXME: The PDTS currently specifies this case as UB, not ill-formed. // However we still diagnose this as an error since until the PDTS is fixed. S.Diag(FD.getLocation(), diag::err_coroutine_promise_requires_return_function) << PromiseRecordDecl; S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here) << PromiseRecordDecl; return false; } else if (HasRVoid) { // If the unqualified-id return_void is found, flowing off the end of a // coroutine is equivalent to a co_return with no operand. Otherwise, // flowing off the end of a coroutine results in undefined behavior. Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr, /*IsImplicit*/false); Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get()); if (Fallthrough.isInvalid()) return false; } this->OnFallthrough = Fallthrough.get(); return true; }
bool Sema::OOPLookupName(LookupResult &R, Scope *S) { assert(getLangOptions().OOP && "Can perform only OOP lookup"); DefinitionName Name = R.getLookupName(); IdentifierResolver::iterator I = IdResolver.begin(Name), IEnd = IdResolver.end(); // First we lookup local scope. for (; S /*&& !isNamespaceOrTranslationUnitScope(S)*/; S = S->getParent()) { DefnContext *Ctx = static_cast<DefnContext *>(S->getEntity()); // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDefnScope(*I); ++I) { if (R.isAcceptableDefn(*I)) { Found = true; R.addDefn(*I); } } if (Found) { R.resolveKind(); if (S->isClassScope()) if (UserClassDefn *Record = dyn_cast_or_null<UserClassDefn>(Ctx)) R.setNamingClass(Record); return true; } if (Ctx) { for (; Ctx; Ctx = Ctx->getParent()) { // We do not look directly into function or method contexts, // since all of the local variables and parameters of the // function/method are present within the Scope. if (Ctx->isFunctionOrMethod()) { continue; } // Perform qualified name lookup into this context. // FIXME: In some cases, we know that every name that could be found by // this qualified name lookup will also be on the identifier chain. For // example, inside a class without any base classes, we never need to // perform qualified lookup because all of the members are on top of the // identifier chain. if (LookupQualifiedName(R, Ctx, /*InUnqualifiedLookup=*/true)) return true; } } } // Stop if we ran out of scopes. // FIXME: This really, really shouldn't be happening. if (!S) return false; // If we are looking for members, no need to look into global/namespace scope. if (R.getLookupKind() == LookupMemberName) return false; return !R.empty(); }
/// 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; }
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; }
//===----------------------------------------------------------------------===// // Sema //===----------------------------------------------------------------------===// bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { DefinitionName Name = R.getLookupName(); if (!Name) return false; // FIXME yabin // LookupNameKind NameKind = R.getLookupKind(); if (!getLangOptions().OOP) { // Unqualified name lookup in non-oop is purely lexical, so // search in the definitions attached to the name. unsigned IDNS = R.getIdentifierNamespace(); // Scan up the scope chain looking for a defn that matches this // identifier that is in the appropriate namespace. This search // should not take long, as shadowing of names is uncommon, and // deep shadowing is extremely uncommon. // bool LeftStartingScope = false; for (IdentifierResolver::iterator I = IdResolver.begin(Name), IEnd = IdResolver.end(); I != IEnd; ++I) { if ((*I)->isInIdentifierNamespace(IDNS)) { R.addDefn(*I); R.resolveKind(); return true; } } } else { // Perform OOP unqualified name lookup. if (OOPLookupName(R, S)) return true; } // 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 top scope, and return it. if (AllowBuiltinCreation) return LookupBuiltin(*this, R); 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(); }