Example #1
0
oop* InterpretedIC::inline_cache_miss() {
  NoGCVerifier noGC;

  // get ic info
  frame           f         = DeltaProcess::active()->last_frame();
  InterpretedIC*  ic        = f.current_interpretedIC();
  Bytecodes::Code send_code = ic->send_code();

  oop receiver = ic->argument_spec() == Bytecodes::args_only // Are we at a self or super send?
    ? f.receiver()                                //  yes: take receiver of frame
    : f.expr(ic->nof_arguments());                //  no:  take receiver pushed before the arguments

  // do the lookup
  klassOop klass = receiver->klass();
  LookupResult result = Bytecodes::is_super_send(send_code)
    ? interpreter_super_lookup(ic->selector())
    : interpreter_normal_lookup(klass, ic->selector());

  // tracing
  if (TraceInlineCacheMiss) {
    std->print("IC miss, ");  trace_inline_cache_miss(ic, klass, result);
  }
  // handle the lookup result
  if (!result.is_empty()) {
    update_inline_cache(ic, &f, ic->send_code(), klass, result);
    return NULL;
  } else {
    return cacheMissResult(does_not_understand(receiver, ic, &f), 
      ic->nof_arguments() + (ic->argument_spec() == Bytecodes::args_only ? 0 : 1))->objs(1);
  }
}
Example #2
0
RasterImage::WillDrawOpaqueNow()
{
  if (!IsOpaque()) {
    return false;
  }

  if (mAnimationState) {
    // We never discard frames of animated images.
    return true;
  }

  // If we are not locked our decoded data could get discard at any time (ie
  // between the call to this function and when we are asked to draw), so we
  // have to return false if we are unlocked.
  if (IsUnlocked()) {
    return false;
  }

  LookupResult result =
    SurfaceCache::LookupBestMatch(ImageKey(this),
                                  RasterSurfaceKey(mSize,
                                                   DefaultSurfaceFlags(),
                                                   PlaybackType::eStatic));
  MatchType matchType = result.Type();
  if (matchType == MatchType::NOT_FOUND || matchType == MatchType::PENDING ||
      !result.Surface()->IsFinished()) {
    return false;
  }

  return true;
}
Example #3
0
QList<Coordinate> CollisionMapEntry::compile() const
{
	QList<Coordinate> points;

	foreach(const Coordinate &coordinate, m_coordinates)
	{
		int offset = 1;
		int size = offset * 2;
		int x = coordinate.first;
		int y = coordinate.second;
		int hits = 0;

		for(int xr = x - offset; xr < x + size; xr++)
		{
			for(int yr = y - offset; yr < y + size; yr++)
			{
				Coordinate query(xr, yr);
				LookupResult result = m_coordinates.contains(query);

				if(result.isValid())
				{
					hits++;
				}
			}
		}

		if(hits < 8)
		{
			points << coordinate;
		}
	}
  bool DynamicIDHandler::IsDynamicLookup (LookupResult& R, Scope* S) {
    if (R.getLookupKind() != Sema::LookupOrdinaryName) return false;
    if (R.isForRedeclaration()) 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 (m_Sema->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())) {
        return !Ctx->isDependentContext();
      }
    }

    return true;
  }
Example #5
0
already_AddRefed<gfxDrawable>
VectorImage::LookupCachedSurface(const SVGDrawingParameters& aParams)
{
  // If we're not allowed to use a cached surface, don't attempt a lookup.
  if (aParams.flags & FLAG_BYPASS_SURFACE_CACHE) {
    return nullptr;
  }

  // We don't do any caching if we have animation, so don't bother with a lookup
  // in this case either.
  if (mHaveAnimations) {
    return nullptr;
  }

  LookupResult result =
    SurfaceCache::Lookup(ImageKey(this),
                         VectorSurfaceKey(aParams.size, aParams.svgContext));
  if (!result) {
    return nullptr;  // No matching surface, or the OS freed the volatile buffer.
  }

  RefPtr<SourceSurface> sourceSurface = result.Surface()->GetSourceSurface();
  if (!sourceSurface) {
    // Something went wrong. (Probably a GPU driver crash or device reset.)
    // Attempt to recover.
    RecoverFromLossOfSurfaces();
    return nullptr;
  }

  RefPtr<gfxDrawable> svgDrawable =
    new gfxSurfaceDrawable(sourceSurface, result.Surface()->GetSize());
  return svgDrawable.forget();
}
  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;
  }
Example #7
0
ExprResult Sema::BuildDefinitionNameExpr(LookupResult &R, bool ADL) {
	if(R.isSingleResult()) {
		return BuildDefinitionNameExpr(R.getLookupNameInfo(),
		                               R.getFoundDefn());
	}
	return ExprError();
}
Example #8
0
LookupResult
FrameAnimator::GetCompositedFrame(AnimationState& aState)
{
  // If we have a composited version of this frame, return that.
  if (mLastCompositedFrameIndex >= 0 &&
      (uint32_t(mLastCompositedFrameIndex) == aState.mCurrentAnimationFrameIndex)) {
    return LookupResult(DrawableSurface(mCompositingFrame->DrawableRef()),
                        MatchType::EXACT);
  }

  // Otherwise return the raw frame. DoBlend is required to ensure that we only
  // hit this case if the frame is not paletted and doesn't require compositing.
  LookupResult result =
    SurfaceCache::Lookup(ImageKey(mImage),
                         RasterSurfaceKey(mSize,
                                          DefaultSurfaceFlags(),
                                          PlaybackType::eAnimated));
  if (!result) {
    return result;
  }

  // Seek to the appropriate frame. If seeking fails, it means that we couldn't
  // get the frame we're looking for; treat this as if the lookup failed.
  if (NS_FAILED(result.Surface().Seek(aState.mCurrentAnimationFrameIndex))) {
    return LookupResult(MatchType::NOT_FOUND);
  }

  MOZ_ASSERT(!result.Surface()->GetIsPaletted(),
             "About to return a paletted frame");

  return result;
}
Example #9
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;
}
Example #10
0
void InterpretedIC::inline_cache_miss() {
  NoGCVerifier noGC;  

  // get ic info
  frame           f         = DeltaProcess::active()->last_frame();
  InterpretedIC*  ic        = f.current_interpretedIC();
  Bytecodes::Code send_code = ic->send_code();

  oop receiver = ic->argument_spec() == Bytecodes::args_only // Are we at a self or super send?
               ? f.receiver()                                //  yes: take receiver of frame
	       : f.expr(ic->nof_arguments());                //  no:  take receiver pushed before the arguments

  // do the lookup
  klassOop klass = receiver->klass();
  LookupResult result = Bytecodes::is_super_send(send_code)
                      ? interpreter_super_lookup(ic->selector())
                      : interpreter_normal_lookup(klass, ic->selector());

  // tracing
  if (TraceMessageSend) std->print_cr("inline cache miss");
  if (TraceLookup)      trace_inline_cache_miss(ic, klass, result);

  // handle the lookup result
  if (!result.is_empty()) 
    update_inline_cache(ic, &f, send_code, klass, result);
  else {
    does_not_understand(receiver, ic, &f);
    // If the program continues we'll redo the inline_cache_miss
    if (!have_nlr_through_C) inline_cache_miss();
  }
}
Example #11
0
LookupResult TypeChecker::lookupMember(DeclContext *dc,
                                       Type type, DeclName name,
                                       NameLookupOptions options) {
  assert(type->mayHaveMembers());

  LookupResult result;
  NLOptions subOptions = NL_QualifiedDefault;
  if (options.contains(NameLookupFlags::KnownPrivate))
    subOptions |= NL_KnownNonCascadingDependency;
  if (options.contains(NameLookupFlags::DynamicLookup))
    subOptions |= NL_DynamicLookup;
  if (options.contains(NameLookupFlags::IgnoreAccessibility))
    subOptions |= NL_IgnoreAccessibility;

  NominalTypeDecl *nominalLookupType = type->getAnyNominal();

  if (options.contains(NameLookupFlags::ProtocolMembers))
    subOptions |= NL_ProtocolMembers;

  // We handle our own overriding/shadowing filtering.
  subOptions &= ~NL_RemoveOverridden;
  subOptions &= ~NL_RemoveNonVisible;

  // Local function that performs lookup.
  auto doLookup = [&]() {
    result.clear();

    LookupResultBuilder builder(*this, result, dc, options,
                                /*memberLookup*/true);
    SmallVector<ValueDecl *, 4> lookupResults;
    dc->lookupQualified(type, name, subOptions, this, lookupResults);

    for (auto found : lookupResults) {
      builder.add(found, nominalLookupType, type);
    }
  };

  doLookup();

  if (result.empty()) {
    // If we didn't find anything, /and/ this is a nominal type, check to see
    // if any of the nominal's protocols are derivable and contain the
    // name we're looking for. (Note that we are not including extensions
    // here -- default derivation doesn't apply in extensions.)
    if (!nominalLookupType)
      return result;
    
    // Force the creation of any delayed members, to ensure proper member
    // lookup.
    this->forceExternalDeclMembers(nominalLookupType);

    // Perform the lookup again.
    // FIXME: This is only because forceExternalDeclMembers() might do something
    // interesting.
    doLookup();
  }

  return result;
}
Example #12
0
RawAccessFrameRef
FrameAnimator::GetRawFrame(uint32_t aFrameNum) const
{
  LookupResult result =
    SurfaceCache::Lookup(ImageKey(mImage),
                         RasterSurfaceKey(mSize,
                                          DefaultSurfaceFlags(),
                                          aFrameNum));
  return result ? result.DrawableRef()->RawAccessRef()
                : RawAccessFrameRef();
}
  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 #14
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 #15
0
void TypeChecker::performTypoCorrection(DeclContext *DC, DeclRefKind refKind,
                                        Type baseTypeOrNull,
                                        DeclName targetDeclName,
                                        SourceLoc nameLoc,
                                        NameLookupOptions lookupOptions,
                                        LookupResult &result,
                                        unsigned maxResults) {
  // Disable typo-correction if we won't show the diagnostic anyway.
  if (getLangOpts().DisableTypoCorrection ||
      (Diags.hasFatalErrorOccurred() &&
       !Diags.getShowDiagnosticsAfterFatalError()))
    return;

  // Fill in a collection of the most reasonable entries.
  TopCollection<unsigned, ValueDecl*> entries(maxResults);
  auto consumer = makeDeclConsumer([&](ValueDecl *decl,
                                       DeclVisibilityKind reason) {
    // Never match an operator with an identifier or vice-versa; this is
    // not a plausible typo.
    if (!isPlausibleTypo(refKind, targetDeclName, decl))
      return;

    // Don't suggest a variable within its own initializer.
    if (auto var = dyn_cast<VarDecl>(decl)) {
      if (isLocInVarInit(*this, var, nameLoc))
        return;
    }

    // Don't waste time computing edit distances that are more than
    // the worst in our collection.
    unsigned maxDistance =
      entries.getMinUninterestingScore(UnreasonableCallEditDistance);

    unsigned distance =
      getCallEditDistance(targetDeclName, decl->getFullName(), maxDistance);

    // Ignore values that are further than a reasonable distance.
    if (distance >= UnreasonableCallEditDistance)
      return;

    entries.insert(distance, std::move(decl));
  });

  TypoCorrectionResolver resolver(*this, nameLoc);
  if (baseTypeOrNull) {
    lookupVisibleMemberDecls(consumer, baseTypeOrNull, DC, &resolver,
                             /*include instance members*/ true);
  } else {
    lookupVisibleDecls(consumer, DC, &resolver, /*top level*/ true, nameLoc);
  }

  // Impose a maximum distance from the best score.
  entries.filterMaxScoreRange(MaxCallEditDistanceFromBestCandidate);

  for (auto &entry : entries)
    result.add({ entry.Value, nullptr });
}
Example #16
0
 LookupResult lookup(klassOop klass, symbolOop selector) {
   if (!match(klass, selector)) {
     _result = interpreter_normal_lookup(klass, selector);
     if (!_result.is_empty()) {
       _key.initialize(klass, selector);
     }
   }
   return _result;
 }
Example #17
0
void InterpretedIC::trace_inline_cache_miss(InterpretedIC* ic, klassOop klass, LookupResult result) {
  std->print("InterpretedIC lookup (");
  klass->print_value();
  std->print(", ");
  ic->selector()->print_value();
  std->print(") --> ");
  result.print_short_on(std);
  std->cr();
}
Example #18
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 #19
0
LookupResult
FrameAnimator::GetCompositedFrame(uint32_t aFrameNum)
{
  MOZ_ASSERT(aFrameNum != 0, "First frame is never composited");

  // If we have a composited version of this frame, return that.
  if (mLastCompositedFrameIndex == int32_t(aFrameNum)) {
    return LookupResult(mCompositingFrame->DrawableRef(), MatchType::EXACT);
  }

  // Otherwise return the raw frame. DoBlend is required to ensure that we only
  // hit this case if the frame is not paletted and doesn't require compositing.
  LookupResult result =
    SurfaceCache::Lookup(ImageKey(mImage),
                         RasterSurfaceKey(mSize,
                                          DefaultSurfaceFlags(),
                                          aFrameNum));
  MOZ_ASSERT(!result || !result.DrawableRef()->GetIsPaletted(),
             "About to return a paletted frame");
  return result;
}
Example #20
0
RawAccessFrameRef
FrameAnimator::GetRawFrame(uint32_t aFrameNum) const
{
  LookupResult result =
    SurfaceCache::Lookup(ImageKey(mImage),
                         RasterSurfaceKey(mSize,
                                          DefaultSurfaceFlags(),
                                          PlaybackType::eAnimated));
  if (!result) {
    return RawAccessFrameRef();
  }

  // Seek to the frame we want. If seeking fails, it means we couldn't get the
  // frame we're looking for, so we bail here to avoid returning the wrong frame
  // to the caller.
  if (NS_FAILED(result.Surface().Seek(aFrameNum))) {
    return RawAccessFrameRef();  // Not available yet.
  }

  return result.Surface()->RawAccessRef();
}
    void FindAndCacheRuntimeLookupResult() {
      assert(!m_clingthrowIfInvalidPointerCache && "Called multiple times!?");

      DeclarationName Name
        = &m_Context.Idents.get("cling_runtime_internal_throwIfInvalidPointer");
      SourceLocation noLoc;
      m_clingthrowIfInvalidPointerCache = new LookupResult(m_Sema, Name, noLoc,
                                        Sema::LookupOrdinaryName,
                                        Sema::ForRedeclaration);
      m_Sema.LookupQualifiedName(*m_clingthrowIfInvalidPointerCache,
                                 m_Context.getTranslationUnitDecl());
      assert(!m_clingthrowIfInvalidPointerCache->empty() &&
              "Lookup of cling_runtime_internal_throwIfInvalidPointer failed!");
    }
Example #22
0
// With -fcuda-host-device-constexpr, an unattributed constexpr function is
// treated as implicitly __host__ __device__, unless:
//  * it is a variadic function (device-side variadic functions are not
//    allowed), or
//  * a __device__ function with this signature was already declared, in which
//    case in which case we output an error, unless the __device__ decl is in a
//    system header, in which case we leave the constexpr function unattributed.
//
// In addition, all function decls are treated as __host__ __device__ when
// ForceCUDAHostDeviceDepth > 0 (corresponding to code within a
//   #pragma clang force_cuda_host_device_begin/end
// pair).
void Sema::maybeAddCUDAHostDeviceAttrs(Scope *S, FunctionDecl *NewD,
                                       const LookupResult &Previous) {
  assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");

  if (ForceCUDAHostDeviceDepth > 0) {
    if (!NewD->hasAttr<CUDAHostAttr>())
      NewD->addAttr(CUDAHostAttr::CreateImplicit(Context));
    if (!NewD->hasAttr<CUDADeviceAttr>())
      NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
    return;
  }

  if (!getLangOpts().CUDAHostDeviceConstexpr || !NewD->isConstexpr() ||
      NewD->isVariadic() || NewD->hasAttr<CUDAHostAttr>() ||
      NewD->hasAttr<CUDADeviceAttr>() || NewD->hasAttr<CUDAGlobalAttr>())
    return;

  // Is D a __device__ function with the same signature as NewD, ignoring CUDA
  // attributes?
  auto IsMatchingDeviceFn = [&](NamedDecl *D) {
    if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(D))
      D = Using->getTargetDecl();
    FunctionDecl *OldD = D->getAsFunction();
    return OldD && OldD->hasAttr<CUDADeviceAttr>() &&
           !OldD->hasAttr<CUDAHostAttr>() &&
           !IsOverload(NewD, OldD, /* UseMemberUsingDeclRules = */ false,
                       /* ConsiderCudaAttrs = */ false);
  };
  auto It = llvm::find_if(Previous, IsMatchingDeviceFn);
  if (It != Previous.end()) {
    // We found a __device__ function with the same name and signature as NewD
    // (ignoring CUDA attrs).  This is an error unless that function is defined
    // in a system header, in which case we simply return without making NewD
    // host+device.
    NamedDecl *Match = *It;
    if (!getSourceManager().isInSystemHeader(Match->getLocation())) {
      Diag(NewD->getLocation(),
           diag::err_cuda_unattributed_constexpr_cannot_overload_device)
          << NewD->getName();
      Diag(Match->getLocation(),
           diag::note_cuda_conflicting_device_function_declared_here);
    }
    return;
  }

  NewD->addAttr(CUDAHostAttr::CreateImplicit(Context));
  NewD->addAttr(CUDADeviceAttr::CreateImplicit(Context));
}
Example #23
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 #24
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 #25
0
/// 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);
    }
  }
}
Example #26
0
void InterpretedIC::replace(LookupResult result, klassOop receiver_klass) {
  // IC entries before modification - used for loging only
  Bytecodes::Code code_before  = send_code();
  oop             word1_before = first_word();
  oop             word2_before = second_word();
  int             transition   = 0;
  // modify IC
  guarantee(word2_before == receiver_klass, "klass should be the same");
  if (result.is_empty()) {
    clear();
    transition = 1;
  } else if (result.is_method()) {
    if (send_type() == Bytecodes::megamorphic_send) {
      set(send_code(), result.method(), receiver_klass);
      transition = 2;
    } else {
      // Please Fix this Robert
      // implement set_monomorphic(klass, method)
      clear();
      transition = 3;
    }
  } else {
    if (send_type() == Bytecodes::megamorphic_send) {
      set(send_code(), oop(result.entry()), receiver_klass);
      transition = 4;
    } else {
      assert(result.is_entry(), "must be jump table entry");
      // a jump table entry of a nmethod is found so let's update the current send
      set(Bytecodes::compiled_send_code_for(send_code()), oop(result.entry()), receiver_klass);
      transition = 5;
    }
  }
  // IC entries after modification - used for loging only
  Bytecodes::Code code_after  = send_code();
  oop             word1_after = first_word();
  oop             word2_after = second_word();
  // log modification
  LOG_EVENT3("InterpretedIC::replace: IC at 0x%x: entry for klass 0x%x replaced (transition %d)", this, receiver_klass, transition);
  LOG_EVENT3("  from (%s, 0x%x, 0x%x)", Bytecodes::name(code_before), word1_before, word2_before);
  LOG_EVENT3("  to   (%s, 0x%x, 0x%x)", Bytecodes::name(code_after ), word1_after , word2_after );
}
Example #27
0
VectorImage::Draw(gfxContext* aContext,
                  const nsIntSize& aSize,
                  const ImageRegion& aRegion,
                  uint32_t aWhichFrame,
                  Filter aFilter,
                  const Maybe<SVGImageContext>& aSVGContext,
                  uint32_t aFlags)
{
  if (aWhichFrame > FRAME_MAX_VALUE) {
    return DrawResult::BAD_ARGS;
  }

  if (!aContext) {
    return DrawResult::BAD_ARGS;
  }

  if (mError) {
    return DrawResult::BAD_IMAGE;
  }

  if (!mIsFullyLoaded) {
    return DrawResult::NOT_READY;
  }

  if (mIsDrawing) {
    NS_WARNING("Refusing to make re-entrant call to VectorImage::Draw");
    return DrawResult::TEMPORARY_ERROR;
  }

  if (mAnimationConsumers == 0 && mProgressTracker) {
    mProgressTracker->OnUnlockedDraw();
  }

  AutoRestore<bool> autoRestoreIsDrawing(mIsDrawing);
  mIsDrawing = true;

  Maybe<SVGImageContext> svgContext;
  // If FLAG_FORCE_PRESERVEASPECTRATIO_NONE bit is set, that mean we should
  // overwrite SVG preserveAspectRatio attibute of this image with none, and
  // always stretch this image to viewport non-uniformly.
  // And we can do this only if the caller pass in the the SVG viewport, via
  // aSVGContext.
  if ((aFlags & FLAG_FORCE_PRESERVEASPECTRATIO_NONE) && aSVGContext.isSome()) {
    Maybe<SVGPreserveAspectRatio> aspectRatio =
      Some(SVGPreserveAspectRatio(SVG_PRESERVEASPECTRATIO_NONE,
                                  SVG_MEETORSLICE_UNKNOWN));
    svgContext =
      Some(SVGImageContext(aSVGContext->GetViewportSize(),
                           aspectRatio));
  } else {
    svgContext = aSVGContext;
  }

  float animTime =
    (aWhichFrame == FRAME_FIRST) ? 0.0f
                                 : mSVGDocumentWrapper->GetCurrentTime();
  AutoSVGRenderingState autoSVGState(svgContext, animTime,
                                     mSVGDocumentWrapper->GetRootSVGElem());


  SVGDrawingParameters params(aContext, aSize, aRegion, aFilter,
                              svgContext, animTime, aFlags);

  if (aFlags & FLAG_BYPASS_SURFACE_CACHE) {
    CreateSurfaceAndShow(params);
    return DrawResult::SUCCESS;
  }

  LookupResult result =
    SurfaceCache::Lookup(ImageKey(this),
                         VectorSurfaceKey(params.size,
                                          params.svgContext,
                                          params.animationTime));

  // Draw.
  if (result) {
    RefPtr<SourceSurface> surface = result.DrawableRef()->GetSurface();
    if (surface) {
      RefPtr<gfxDrawable> svgDrawable =
        new gfxSurfaceDrawable(surface, result.DrawableRef()->GetSize());
      Show(svgDrawable, params);
      return DrawResult::SUCCESS;
    }

    // We lost our surface due to some catastrophic event.
    RecoverFromLossOfSurfaces();
  }

  CreateSurfaceAndShow(params);

  return DrawResult::SUCCESS;
}
Example #28
0
Optional<Type> TypeChecker::checkObjCKeyPathExpr(DeclContext *dc,
                                                 ObjCKeyPathExpr *expr,
                                                 bool requireResultType) {
  // If there is already a semantic expression, do nothing.
  if (expr->getSemanticExpr() && !requireResultType) return None;

  // #keyPath only makes sense when we have the Objective-C runtime.
  if (!Context.LangOpts.EnableObjCInterop) {
    diagnose(expr->getLoc(), diag::expr_keypath_no_objc_runtime);

    expr->setSemanticExpr(
      new (Context) StringLiteralExpr("", expr->getSourceRange(),
                                      /*Implicit=*/true));
    return None;
  }

  // The key path string we're forming.
  SmallString<32> keyPathScratch;
  llvm::raw_svector_ostream keyPathOS(keyPathScratch);

  // Captures the state of semantic resolution.
  enum State {
    Beginning,
    ResolvingType,
    ResolvingProperty,
    ResolvingArray,
    ResolvingSet,
    ResolvingDictionary,
  } state = Beginning;
  
  /// Determine whether we are currently resolving a property.
  auto isResolvingProperty = [&] {
    switch (state) {
    case Beginning:
    case ResolvingType:
      return false;

    case ResolvingProperty:
    case ResolvingArray:
    case ResolvingSet:
    case ResolvingDictionary:
      return true;
    }
  };

  // The type of AnyObject, which is used whenever we don't have
  // sufficient type information.
  Type anyObjectType;
  if (auto anyObject = Context.getProtocol(KnownProtocolKind::AnyObject)) {
    validateDecl(anyObject);
    anyObjectType = anyObject->getDeclaredInterfaceType();
  } else {
    diagnose(expr->getLoc(), diag::stdlib_anyobject_not_found);
    return None;
  }

  // Local function to update the state after we've resolved a
  // component.
  Type currentType;
  auto updateState = [&](bool isProperty, Type newType) {
    // Strip off optionals.
    newType = newType->lookThroughAllAnyOptionalTypes();

    // If updating to a type, just set the new type; there's nothing
    // more to do.
    if (!isProperty) {
      assert(state == Beginning || state == ResolvingType);
      state = ResolvingType;
      currentType = newType;
      return;
    }

    // We're updating to a property. Determine whether we're looking
    // into a bridged Swift collection of some sort.
    if (auto boundGeneric = newType->getAs<BoundGenericType>()) {
      auto nominal = boundGeneric->getDecl();

      // Array<T>
      if (nominal == Context.getArrayDecl()) {
        // Further lookups into the element type.
        state = ResolvingArray;
        currentType = boundGeneric->getGenericArgs()[0];
        return;
      }

      // Set<T>
      if (nominal == Context.getSetDecl()) {
        // Further lookups into the element type.
        state = ResolvingSet;
        currentType = boundGeneric->getGenericArgs()[0];
        return;
      }

      // Dictionary<K, V>
      if (nominal == Context.getDictionaryDecl()) {
        // Key paths look into the keys of a dictionary; further
        // lookups into the value type.
        state = ResolvingDictionary;
        currentType = boundGeneric->getGenericArgs()[1];
        return;
      }
    }

    // Determine whether we're looking into a Foundation collection.
    if (auto classDecl = newType->getClassOrBoundGenericClass()) {
      if (classDecl->isObjC() && classDecl->hasClangNode()) {
        SmallString<32> scratch;
        StringRef objcClassName = classDecl->getObjCRuntimeName(scratch);

        // NSArray
        if (objcClassName == "NSArray") {
          // The element type is unknown, so use AnyObject.
          state = ResolvingArray;
          currentType = anyObjectType;
          return;
        }

        // NSSet
        if (objcClassName == "NSSet") {
          // The element type is unknown, so use AnyObject.
          state = ResolvingSet;
          currentType = anyObjectType;
          return;
        }

        // NSDictionary
        if (objcClassName == "NSDictionary") {
          // Key paths look into the keys of a dictionary; there's no
          // type to help us here.
          state = ResolvingDictionary;
          currentType = anyObjectType;
          return;
        }
      }
    }

    // It's just a property.
    state = ResolvingProperty;
    currentType = newType;
  };
  
  // Local function to perform name lookup for the current index.
  auto performLookup = [&](unsigned idx, Identifier componentName,
                           SourceLoc componentNameLoc) -> LookupResult {
    if (state == Beginning)
      return lookupUnqualified(dc, componentName, componentNameLoc);

    assert(currentType && "Non-beginning state must have a type");

    // Determine the type in which the lookup should occur. If we have
    // a bridged value type, this will be the Objective-C class to
    // which it is bridged.
    Type lookupType;
    if (auto bridgedClass = Context.getBridgedToObjC(dc, currentType))
      lookupType = bridgedClass;
    else
      lookupType = currentType;

    // Look for a member with the given name within this type.
    return lookupMember(dc, lookupType, componentName);
  };

  // Local function to print a component to the string.
  bool needDot = false;
  auto printComponent = [&](Identifier component) {
    if (needDot)
      keyPathOS << ".";
    else
      needDot = true;

    keyPathOS << component.str();
  };

  bool isInvalid = false;
  for (unsigned idx : range(expr->getNumComponents())) {
    auto componentName = expr->getComponentName(idx);
    auto componentNameLoc = expr->getComponentNameLoc(idx);

    // If we are resolving into a dictionary, any component is
    // well-formed because the keys are unknown dynamically.
    if (state == ResolvingDictionary) {
      // Just print the component unchanged; there's no checking we
      // can do here.
      printComponent(componentName);

      // From here, we're resolving a property. Use the current type.
      updateState(/*isProperty=*/true, currentType);

      continue;
    }

    // Look for this component.
    LookupResult lookup = performLookup(idx, componentName, componentNameLoc);

    // If we didn't find anything, try to apply typo-correction.
    bool resultsAreFromTypoCorrection = false;
    if (!lookup) {
      performTypoCorrection(dc, DeclRefKind::Ordinary, currentType,
                            componentName, componentNameLoc,
                            (currentType ? defaultMemberTypeLookupOptions
                                         : defaultUnqualifiedLookupOptions),
                            lookup);

      if (currentType)
        diagnose(componentNameLoc, diag::could_not_find_type_member,
                 currentType, componentName);
      else
        diagnose(componentNameLoc, diag::use_unresolved_identifier,
                 componentName, false);

      // Note all the correction candidates.
      for (auto &result : lookup) {
        noteTypoCorrection(componentName, DeclNameLoc(componentNameLoc),
                           result);
      }

      isInvalid = true;
      if (!lookup) break;

      // Remember that these are from typo correction.
      resultsAreFromTypoCorrection = true;
    }

    // If we have more than one result, filter out unavailable or
    // obviously unusable candidates.
    if (lookup.size() > 1) {
      lookup.filter([&](LookupResult::Result result) -> bool {
          // Drop unavailable candidates.
          if (result->getAttrs().isUnavailable(Context))
            return false;

          // Drop non-property, non-type candidates.
          if (!isa<VarDecl>(result.Decl) && !isa<TypeDecl>(result.Decl))
            return false;

          return true;
      });
    }

    // If we *still* have more than one result, fail.
    if (lookup.size() > 1) {
      // Don't diagnose ambiguities if the results are from typo correction.
      if (resultsAreFromTypoCorrection)
        break;

      if (currentType)
        diagnose(componentNameLoc, diag::ambiguous_member_overload_set,
                 componentName);
      else
        diagnose(componentNameLoc, diag::ambiguous_decl_ref,
                 componentName);

      for (auto result : lookup) {
        diagnose(result, diag::decl_declared_here, result->getFullName());
      }
      isInvalid = true;
      break;
    }

    auto found = lookup.front().Decl;

    // Handle property references.
    if (auto var = dyn_cast<VarDecl>(found)) {
      validateDecl(var);

      // Resolve this component to the variable we found.
      expr->resolveComponent(idx, var);
      updateState(/*isProperty=*/true, var->getType()->getRValueObjectType());

      // Check that the property is @objc.
      if (!var->isObjC()) {
        diagnose(componentNameLoc, diag::expr_keypath_non_objc_property,
                 componentName);
        if (var->getLoc().isValid() && var->getDeclContext()->isTypeContext()) {
          diagnose(var, diag::make_decl_objc,
                   var->getDescriptiveKind())
            .fixItInsert(var->getAttributeInsertionLoc(false),
                         "@objc ");
        }
      } else {
        // FIXME: Warn about non-KVC-compliant getter/setter names?
      }

      // Print the Objective-C property name.
      printComponent(var->getObjCPropertyName());
      continue;
    }

    // Handle type references.
    if (auto type = dyn_cast<TypeDecl>(found)) {
      // We cannot refer to a type via a property.
      if (isResolvingProperty()) {
        diagnose(componentNameLoc, diag::expr_keypath_type_of_property,
                 componentName, currentType);
        isInvalid = true;
        break;
      }

      // We cannot refer to a generic type.
      if (type->getDeclaredInterfaceType()->hasTypeParameter()) {
        diagnose(componentNameLoc, diag::expr_keypath_generic_type,
                 componentName);
        isInvalid = true;
        break;
      }

      Type newType;
      if (currentType && !currentType->isAnyObject()) {
        newType = currentType->getTypeOfMember(dc->getParentModule(), type,
                                               this);
      } else {
        newType = type->getDeclaredInterfaceType();
      }
      if (!newType) {
        isInvalid = true;
        break;
      }

      updateState(/*isProperty=*/false, newType);
      continue;
    }

    // Declarations that cannot be part of a key-path.
    diagnose(componentNameLoc, diag::expr_keypath_not_property,
             found->getDescriptiveKind(), found->getFullName());
    isInvalid = true;
    break;
  }

  // Check for an empty key-path string.
  auto keyPathString = keyPathOS.str();
  if (keyPathString.empty() && !isInvalid)
    diagnose(expr->getLoc(), diag::expr_keypath_empty);

  // Set the semantic expression.
  if (!expr->getSemanticExpr()) {
    expr->setSemanticExpr(
      new (Context) StringLiteralExpr(Context.AllocateCopy(keyPathString),
                                      expr->getSourceRange(),
                                      /*Implicit=*/true));
  }

  if (!currentType) return None;
  return currentType;
}
Example #29
0
  bool DeclExtractor::CheckTagDeclaration(TagDecl* NewTD,
                                          LookupResult& Previous){
    // If the decl is already known invalid, don't check it.
    if (NewTD->isInvalidDecl())
      return false;

    IdentifierInfo* Name = NewTD->getIdentifier();
    // If this is not a definition, it must have a name.
    assert((Name != 0 || NewTD->isThisDeclarationADefinition()) &&
           "Nameless record must be a definition!");

    // Figure out the underlying type if this a enum declaration. We need to do
    // this early, because it's needed to detect if this is an incompatible
    // redeclaration.

    TagDecl::TagKind Kind = NewTD->getTagKind();
    bool Invalid = false;
    assert(NewTD->getNumTemplateParameterLists() == 0
           && "Cannot handle that yet!");
    bool isExplicitSpecialization = false;

    if (Kind == TTK_Enum) {
      EnumDecl* ED = cast<EnumDecl>(NewTD);
      bool ScopedEnum = ED->isScoped();
      const QualType QT = ED->getIntegerType();

      if (QT.isNull() && ScopedEnum)
        // No underlying type explicitly specified, or we failed to parse the
        // type, default to int.
        ; //EnumUnderlying = m_Context->IntTy.getTypePtr();
      else if (!QT.isNull()) {
        // C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an
        // integral type; any cv-qualification is ignored.

        SourceLocation UnderlyingLoc;
        TypeSourceInfo* TI = 0;
        if ((TI = ED->getIntegerTypeSourceInfo()))
          UnderlyingLoc = TI->getTypeLoc().getBeginLoc();

        if (!QT->isDependentType() && !QT->isIntegralType(*m_Context)) {
          m_Sema->Diag(UnderlyingLoc, diag::err_enum_invalid_underlying)
            << QT;
        }
        if (TI)
          m_Sema->DiagnoseUnexpandedParameterPack(UnderlyingLoc, TI,
                                                Sema::UPPC_FixedUnderlyingType);
      }
    }

    DeclContext *SearchDC = m_Sema->CurContext;
    DeclContext *DC = m_Sema->CurContext;
    //bool isStdBadAlloc = false;
    SourceLocation NameLoc = NewTD->getLocation();
    // if (Name && SS.isNotEmpty()) {
    //   // We have a nested-name tag ('struct foo::bar').

    //   // Check for invalid 'foo::'.
    //   if (SS.isInvalid()) {
    //     Name = 0;
    //     goto CreateNewDecl;
    //   }

    //   // If this is a friend or a reference to a class in a dependent
    //   // context, don't try to make a decl for it.
    //   if (TUK == TUK_Friend || TUK == TUK_Reference) {
    //     DC = computeDeclContext(SS, false);
    //     if (!DC) {
    //       IsDependent = true;
    //       return 0;
    //     }
    //   } else {
    //     DC = computeDeclContext(SS, true);
    //     if (!DC) {
    //       Diag(SS.getRange().getBegin(),
    //            diag::err_dependent_nested_name_spec)
    //         << SS.getRange();
    //       return 0;
    //     }
    //   }

    //   if (RequireCompleteDeclContext(SS, DC))
    //     return 0;

    //   SearchDC = DC;
    //   // Look-up name inside 'foo::'.
    //   LookupQualifiedName(Previous, DC);

    //   if (Previous.isAmbiguous())
    //     return 0;

    //   if (Previous.empty()) {
    //     // Name lookup did not find anything. However, if the
    //     // nested-name-specifier refers to the current instantiation,
    //     // and that current instantiation has any dependent base
    //     // classes, we might find something at instantiation time: treat
    //     // this as a dependent elaborated-type-specifier.
    //     // But this only makes any sense for reference-like lookups.
    //     if (Previous.wasNotFoundInCurrentInstantiation() &&
    //         (TUK == TUK_Reference || TUK == TUK_Friend)) {
    //       IsDependent = true;
    //       return 0;
    //     }

    //     // A tag 'foo::bar' must already exist.
    //     Diag(NameLoc, diag::err_not_tag_in_scope)
    //       << Kind << Name << DC << SS.getRange();
    //     Name = 0;
    //     Invalid = true;
    //   goto CreateNewDecl;
    // }
    //} else
    if (Name) {
      // If this is a named struct, check to see if there was a previous forward
      // declaration or definition.
      // FIXME: We're looking into outer scopes here, even when we
      // shouldn't be. Doing so can result in ambiguities that we
      // shouldn't be diagnosing.

      //LookupName(Previous, S);

      if (Previous.isAmbiguous()) {
        LookupResult::Filter F = Previous.makeFilter();
        while (F.hasNext()) {
          NamedDecl *ND = F.next();
          if (ND->getDeclContext()->getRedeclContext() != SearchDC)
            F.erase();
        }
        F.done();
      }

      // Note:  there used to be some attempt at recovery here.
      if (Previous.isAmbiguous()) {
        return false;
      }

      if (!m_Sema->getLangOpts().CPlusPlus) {
        // FIXME: This makes sure that we ignore the contexts associated
        // with C structs, unions, and enums when looking for a matching
        // tag declaration or definition. See the similar lookup tweak
        // in Sema::LookupName; is there a better way to deal with this?
        while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC))
          SearchDC = SearchDC->getParent();
      }
    } else if (m_Sema->getScopeForContext(m_Sema->CurContext)
               ->isFunctionPrototypeScope()) {
      // If this is an enum declaration in function prototype scope, set its
      // initial context to the translation unit.
      SearchDC = m_Context->getTranslationUnitDecl();
    }

    if (Previous.isSingleResult() &&
        Previous.getFoundDecl()->isTemplateParameter()) {
      // Maybe we will complain about the shadowed template parameter.
      m_Sema->DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl());
      // Just pretend that we didn't see the previous declaration.
      Previous.clear();
    }

    if (m_Sema->getLangOpts().CPlusPlus && Name && DC && m_Sema->StdNamespace
        && DC->Equals(m_Sema->getStdNamespace()) && Name->isStr("bad_alloc")) {
      // This is a declaration of or a reference to "std::bad_alloc".
      //isStdBadAlloc = true;

      if (Previous.empty() && m_Sema->StdBadAlloc) {
        // std::bad_alloc has been implicitly declared (but made invisible to
        // name lookup). Fill in this implicit declaration as the previous
        // declaration, so that the declarations get chained appropriately.
        Previous.addDecl(m_Sema->getStdBadAlloc());
      }
    }

    if (!Previous.empty()) {
      NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl();

      // It's okay to have a tag decl in the same scope as a typedef
      // which hides a tag decl in the same scope.  Finding this
      // insanity with a redeclaration lookup can only actually happen
      // in C++.
      //
      // This is also okay for elaborated-type-specifiers, which is
      // technically forbidden by the current standard but which is
      // okay according to the likely resolution of an open issue;
      // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407
      if (m_Sema->getLangOpts().CPlusPlus) {
        if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) {
          if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
            TagDecl *Tag = TT->getDecl();
            if (Tag->getDeclName() == Name &&
                Tag->getDeclContext()->getRedeclContext()
                ->Equals(TD->getDeclContext()->getRedeclContext())) {
              PrevDecl = Tag;
              Previous.clear();
              Previous.addDecl(Tag);
              Previous.resolveKind();
            }
          }
        }
      }

      if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
        // If this is a use of a previous tag, or if the tag is already declared
        // in the same scope (so that the definition/declaration completes or
        // rementions the tag), reuse the decl.
        if (m_Sema->isDeclInScope(PrevDecl, SearchDC,
                                 m_Sema->getScopeForContext(m_Sema->CurContext),
                                  isExplicitSpecialization)) {
          // Make sure that this wasn't declared as an enum and now used as a
          // struct or something similar.
          SourceLocation KWLoc = NewTD->getLocStart();
          if (!m_Sema->isAcceptableTagRedeclaration(PrevTagDecl, Kind,
                                          NewTD->isThisDeclarationADefinition(),
                                                    KWLoc, *Name)) {
            bool SafeToContinue
              = (PrevTagDecl->getTagKind() != TTK_Enum && Kind != TTK_Enum);

            if (SafeToContinue)
              m_Sema->Diag(KWLoc, diag::err_use_with_wrong_tag)
                << Name
                << FixItHint::CreateReplacement(SourceRange(KWLoc),
                                                PrevTagDecl->getKindName());
            else
              m_Sema->Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
            m_Sema->Diag(PrevTagDecl->getLocation(), diag::note_previous_use);

            if (SafeToContinue)
              Kind = PrevTagDecl->getTagKind();
            else {
              // Recover by making this an anonymous redefinition.
              Name = 0;
              Previous.clear();
              Invalid = true;
            }
          }

          if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) {
            const EnumDecl *NewEnum = cast<EnumDecl>(NewTD);
            const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl);

            // All conflicts with previous declarations are recovered by
            // returning the previous declaration.
            if (NewEnum->isScoped() != PrevEnum->isScoped()) {
              m_Sema->Diag(KWLoc, diag::err_enum_redeclare_scoped_mismatch)
                << PrevEnum->isScoped();
              m_Sema->Diag(PrevTagDecl->getLocation(), diag::note_previous_use);

              return false;
            }
            else if (PrevEnum->isFixed()) {
              QualType T = NewEnum->getIntegerType();

              if (!m_Context->hasSameUnqualifiedType(T,
                                                  PrevEnum->getIntegerType())) {
                m_Sema->Diag(NameLoc.isValid() ? NameLoc : KWLoc,
                             diag::err_enum_redeclare_type_mismatch)
                  << T
                  << PrevEnum->getIntegerType();
                m_Sema->Diag(PrevTagDecl->getLocation(),
                             diag::note_previous_use);

                return false;
              }
            }
            else if (NewEnum->isFixed() != PrevEnum->isFixed()) {
              m_Sema->Diag(KWLoc, diag::err_enum_redeclare_fixed_mismatch)
                << PrevEnum->isFixed();
              m_Sema->Diag(PrevTagDecl->getLocation(), diag::note_previous_use);

              return false;
            }
          }

          if (!Invalid) {
            // If this is a use, just return the declaration we found.

            // Diagnose attempts to redefine a tag.
            if (NewTD->isThisDeclarationADefinition()) {
              if (TagDecl* Def = PrevTagDecl->getDefinition()) {
                // If we're defining a specialization and the previous
                // definition is from an implicit instantiation, don't emit an
                // error here; we'll catch this in the general case below.
                if (!isExplicitSpecialization ||
                    !isa<CXXRecordDecl>(Def) ||
                    cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind()
                    == TSK_ExplicitSpecialization) {
                  m_Sema->Diag(NameLoc, diag::err_redefinition) << Name;
                  m_Sema->Diag(Def->getLocation(),
                               diag::note_previous_definition);
                  // If this is a redefinition, recover by making this
                  // struct be anonymous, which will make any later
                  // references get the previous definition.
                  Name = 0;
                  Previous.clear();
                  Invalid = true;
                }
              } else {
                // If the type is currently being defined, complain
                // about a nested redefinition.
                const TagType *Tag
                  = cast<TagType>(m_Context->getTagDeclType(PrevTagDecl));
                if (Tag->isBeingDefined()) {
                  m_Sema->Diag(NameLoc, diag::err_nested_redefinition) << Name;
                  m_Sema->Diag(PrevTagDecl->getLocation(),
                               diag::note_previous_definition);
                  Name = 0;
                  Previous.clear();
                  Invalid = true;
                }
              }

              // Okay, this is definition of a previously declared or referenced
              // tag PrevDecl. We're going to create a new Decl for it.
            }
          }
          // If we get here we have (another) forward declaration or we
          // have a definition.  Just create a new decl.

        } else {
          // If we get here, this is a definition of a new tag type in a nested
          // scope, e.g. "struct foo; void bar() { struct foo; }", just create a
          // new decl/type.  We set PrevDecl to NULL so that the entities
          // have distinct types.
          Previous.clear();
        }
        // If we get here, we're going to create a new Decl. If PrevDecl
        // is non-NULL, it's a definition of the tag declared by
        // PrevDecl. If it's NULL, we have a new definition.


        // Otherwise, PrevDecl is not a tag, but was found with tag
        // lookup.  This is only actually possible in C++, where a few
        // things like templates still live in the tag namespace.
      } else {
        assert(m_Sema->getLangOpts().CPlusPlus);

        // Diagnose if the declaration is in scope.
        if (!m_Sema->isDeclInScope(PrevDecl, SearchDC,
                                 m_Sema->getScopeForContext(m_Sema->CurContext),
                                   isExplicitSpecialization)) {
          // do nothing

          // Otherwise it's a declaration.  Call out a particularly common
          // case here.
        } else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(PrevDecl)) {
          unsigned Kind = 0;
          if (isa<TypeAliasDecl>(PrevDecl)) Kind = 1;
          m_Sema->Diag(NameLoc, diag::err_tag_definition_of_typedef)
            << Name << Kind << TND->getUnderlyingType();
          m_Sema->Diag(PrevDecl->getLocation(),
                       diag::note_previous_decl) << PrevDecl;
          Invalid = true;

          // Otherwise, diagnose.
        } else {
          // The tag name clashes with something else in the target scope,
          // issue an error and recover by making this tag be anonymous.
          m_Sema->Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
          m_Sema->Diag(PrevDecl->getLocation(), diag::note_previous_definition);
          Name = 0;
          Invalid = true;
        }

        // The existing declaration isn't relevant to us; we're in a
        // new scope, so clear out the previous declaration.
        Previous.clear();
      }
    }
    if (Invalid) {
      return false;
    }

    return true;
  }
Example #30
0
LookupResult TypeChecker::lookupMember(DeclContext *dc,
                                       Type type, DeclName name,
                                       NameLookupOptions options) {
  LookupResult result;
  NLOptions subOptions = NL_QualifiedDefault;
  if (options.contains(NameLookupFlags::KnownPrivate))
    subOptions |= NL_KnownNonCascadingDependency;
  if (options.contains(NameLookupFlags::DynamicLookup))
    subOptions |= NL_DynamicLookup;
  if (options.contains(NameLookupFlags::IgnoreAccessibility))
    subOptions |= NL_IgnoreAccessibility;

  // Dig out the type that we'll actually be looking into, and determine
  // whether it is a nominal type.
  Type lookupType = type;
  if (auto lvalueType = lookupType->getAs<LValueType>()) {
    lookupType = lvalueType->getObjectType();
  }
  if (auto metaType = lookupType->getAs<MetatypeType>()) {
    lookupType = metaType->getInstanceType();
  }
  NominalTypeDecl *nominalLookupType = lookupType->getAnyNominal();

  /// Whether to consider protocol members or not.
  bool considerProtocolMembers
    = nominalLookupType && !isa<ProtocolDecl>(nominalLookupType) &&
      options.contains(NameLookupFlags::ProtocolMembers);
  if (considerProtocolMembers)
    subOptions |= NL_ProtocolMembers;

  // We handle our own overriding/shadowing filtering.
  subOptions &= ~NL_RemoveOverridden;
  subOptions &= ~NL_RemoveNonVisible;

  // We can't have tuple types here; they need to be handled elsewhere.
  assert(!type->is<TupleType>());

  // Local function that performs lookup.
  auto doLookup = [&]() {
    result.clear();

    LookupResultBuilder builder(*this, result, dc, options,
                                considerProtocolMembers,
                                false);
    SmallVector<ValueDecl *, 4> lookupResults;
    dc->lookupQualified(type, name, subOptions, this, lookupResults);

    for (auto found : lookupResults) {
      builder.add(found, nominalLookupType, type);
    }
  };

  doLookup();

  if (result.empty()) {
    // If we didn't find anything, /and/ this is a nominal type, check to see
    // if any of the nominal's protocols are derivable and contain the
    // name we're looking for. (Note that we are not including extensions
    // here -- default derivation doesn't apply in extensions.)
    if (!nominalLookupType)
      return result;
    
    // Force the creation of any delayed members, to ensure proper member
    // lookup.
    this->forceExternalDeclMembers(nominalLookupType);

    // Perform the lookup again.
    // FIXME: This is only because forceExternalDeclMembers() might do something
    // interesting.
    doLookup();
  }

  return result;
}