Example #1
0
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;
}
Example #2
0
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();
}
Example #3
0
/// 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;
  }
Example #6
0
// 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;
}
Example #7
0
//===----------------------------------------------------------------------===//
// 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;
}
Example #8
0
/// 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();
}
Example #9
0
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();
}