Example #1
0
 bool checkDeclForNamespace(const CXXRecordDecl *decl, std::string concreteNamespace) {
    const DeclContext * context = decl->getCanonicalDecl()->getDeclContext();
    if (context->isNamespace()) {
       NamespaceDecl * nameDecl = NamespaceDecl::castFromDeclContext(context);
       if (nameDecl->getNameAsString() == concreteNamespace) {
          return true;
       }
    }
    return false;
 }
NamespaceDecl *Sema::ActOnEnterRogerFileScopeNamespace(Scope *NamespcScope) {
    IdentifierInfo &II = Context.Idents.get("roger file scope namespace");
    NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, false,
                             SourceLocation(), SourceLocation(), &II, 0);
    Namespc->IsRogerNamespace = true;

    Namespc->setLexicalDeclContext(CurContext);

    //DeclContext->addDecl(Namespc);

    PushDeclContext(NamespcScope, Namespc);

    return Namespc;
}
Example #3
0
void 
DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){
  Contexts.clear();
  
  if (DeclKind != Decl::Namespace) {
    Contexts.push_back(this);
    return;
  }
  
  NamespaceDecl *Self = static_cast<NamespaceDecl *>(this);
  for (NamespaceDecl *N = Self->getMostRecentDecl(); N;
       N = N->getPreviousDecl())
    Contexts.push_back(N);
  
  std::reverse(Contexts.begin(), Contexts.end());
}
static bool singleNamedNamespaceChild(const NamespaceDecl &ND) {
  NamespaceDecl::decl_range Decls = ND.decls();
  if (std::distance(Decls.begin(), Decls.end()) != 1)
    return false;

  const auto *ChildNamespace = dyn_cast<const NamespaceDecl>(*Decls.begin());
  return ChildNamespace && !anonymousOrInlineNamespace(*ChildNamespace);
}
// TODO: Add classes with a finalize() method that specialize FinalizerTrait.
bool RecordInfo::NeedsFinalization() {
  if (does_need_finalization_ == kNotComputed) {
    // Rely on hasNonTrivialDestructor(), but if the only
    // identifiable reason for it being true is the presence
    // of a safely ignorable class as a direct base,
    // or we're processing such an 'ignorable' class, then it does
    // not need finalization.
    does_need_finalization_ =
        record_->hasNonTrivialDestructor() ? kTrue : kFalse;
    if (!does_need_finalization_)
      return does_need_finalization_;

    // Processing a class with a safely-ignorable destructor.
    NamespaceDecl* ns =
        dyn_cast<NamespaceDecl>(record_->getDeclContext());
    if (ns && Config::HasIgnorableDestructor(ns->getName(), name_)) {
      does_need_finalization_ = kFalse;
      return does_need_finalization_;
    }

    CXXDestructorDecl* dtor = record_->getDestructor();
    if (dtor && dtor->isUserProvided())
      return does_need_finalization_;
    for (Fields::iterator it = GetFields().begin();
         it != GetFields().end();
         ++it) {
      if (it->second.edge()->NeedsFinalization())
        return does_need_finalization_;
    }

    for (Bases::iterator it = GetBases().begin();
         it != GetBases().end();
         ++it) {
      if (it->second.info()->NeedsFinalization())
        return does_need_finalization_;
    }
    // Destructor was non-trivial due to bases with destructors that
    // can be safely ignored. Hence, no need for finalization.
    does_need_finalization_ = kFalse;
  }
  return does_need_finalization_;
}
static bool anonymousOrInlineNamespace(const NamespaceDecl &ND) {
  return ND.isAnonymousNamespace() || ND.isInlineNamespace();
}
Edge* RecordInfo::CreateEdge(const Type* type) {
  if (!type) {
    return 0;
  }

  if (type->isPointerType() || type->isReferenceType()) {
    if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull()))
      return new RawPtr(ptr, false, type->isReferenceType());
    return 0;
  }

  RecordInfo* info = cache_->Lookup(type);

  // If the type is neither a pointer or a C++ record we ignore it.
  if (!info) {
    return 0;
  }

  TemplateArgs args;

  if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
    if (Edge* ptr = CreateEdge(args[0]))
      return new RawPtr(ptr, true, false);
    return 0;
  }

  if (Config::IsRefPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
    if (Edge* ptr = CreateEdge(args[0]))
      return new RefPtr(ptr);
    return 0;
  }

  if (Config::IsOwnPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
    if (Edge* ptr = CreateEdge(args[0]))
      return new OwnPtr(ptr);
    return 0;
  }

  if (Config::IsMember(info->name()) && info->GetTemplateArgs(1, &args)) {
    if (Edge* ptr = CreateEdge(args[0]))
      return new Member(ptr);
    return 0;
  }

  if (Config::IsWeakMember(info->name()) && info->GetTemplateArgs(1, &args)) {
    if (Edge* ptr = CreateEdge(args[0]))
      return new WeakMember(ptr);
    return 0;
  }

  if (Config::IsPersistent(info->name())) {
    // Persistent might refer to v8::Persistent, so check the name space.
    // TODO: Consider using a more canonical identification than names.
    NamespaceDecl* ns =
        dyn_cast<NamespaceDecl>(info->record()->getDeclContext());
    if (!ns || ns->getName() != "blink")
      return 0;
    if (!info->GetTemplateArgs(1, &args))
      return 0;
    if (Edge* ptr = CreateEdge(args[0]))
      return new Persistent(ptr);
    return 0;
  }

  if (Config::IsGCCollection(info->name()) ||
      Config::IsWTFCollection(info->name())) {
    bool is_root = Config::IsPersistentGCCollection(info->name());
    bool on_heap = is_root || info->IsHeapAllocatedCollection();
    size_t count = Config::CollectionDimension(info->name());
    if (!info->GetTemplateArgs(count, &args))
      return 0;
    Collection* edge = new Collection(info, on_heap, is_root);
    for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) {
      if (Edge* member = CreateEdge(*it)) {
        edge->members().push_back(member);
      }
      // TODO: Handle the case where we fail to create an edge (eg, if the
      // argument is a primitive type or just not fully known yet).
    }
    return edge;
  }

  return new Value(info);
}
Example #8
0
Edge* RecordInfo::CreateEdge(const Type* type) {
  if (!type) {
    return 0;
  }

  if (type->isPointerType()) {
    if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull()))
      return new RawPtr(ptr);
    return 0;
  }

  RecordInfo* info = cache_->Lookup(type);

  // If the type is neither a pointer or a C++ record we ignore it.
  if (!info) {
    return 0;
  }

  TemplateArgs args;

  if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
    if (Edge* ptr = CreateEdge(args[0]))
      return new RawPtr(ptr);
    return 0;
  }

  if (Config::IsRefPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
    if (Edge* ptr = CreateEdge(args[0]))
      return new RefPtr(ptr);
    return 0;
  }

  if (Config::IsOwnPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
    if (Edge* ptr = CreateEdge(args[0]))
      return new OwnPtr(ptr);
    return 0;
  }

  if (Config::IsMember(info->name()) && info->GetTemplateArgs(1, &args)) {
    if (Edge* ptr = CreateEdge(args[0]))
      return new Member(ptr);
    return 0;
  }

  if (Config::IsWeakMember(info->name()) && info->GetTemplateArgs(1, &args)) {
    if (Edge* ptr = CreateEdge(args[0]))
      return new WeakMember(ptr);
    return 0;
  }

  if (Config::IsPersistent(info->name())) {
    // Persistent might refer to v8::Persistent, so check the name space.
    // TODO: Consider using a more canonical identification than names.
    NamespaceDecl* ns =
        dyn_cast<NamespaceDecl>(info->record()->getDeclContext());
    if (!ns || ns->getName() != "WebCore")
      return 0;
    if (!info->GetTemplateArgs(1, &args))
      return 0;
    if (Edge* ptr = CreateEdge(args[0]))
      return new Persistent(ptr);
    return 0;
  }

  if (Config::IsGCCollection(info->name()) ||
      Config::IsWTFCollection(info->name())) {
    bool is_root = Config::IsPersistentGCCollection(info->name());
    bool on_heap = is_root || info->IsHeapAllocatedCollection();
    size_t count = Config::CollectionDimension(info->name());
    if (!info->GetTemplateArgs(count, &args))
      return 0;
    Collection* edge = new Collection(info, on_heap, is_root);
    for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) {
      if (Edge* member = CreateEdge(*it)) {
        edge->members().push_back(member);
      } else {
        // We failed to create an edge so abort the entire edge construction.
        delete edge;  // Will delete the already allocated members.
        return 0;
      }
    }
    return edge;
  }

  return new Value(info);
}
NamespaceDecl *Sema::ActOnRogerNamespaceHeaderPart(DeclContext *DeclContext, IdentifierInfo *II,
        SourceLocation IdentLoc,
        AttributeList *AttrList) {
    // set CurContext

    SourceLocation NamespaceLoc;
    SourceLocation InlineLoc;
    SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;

    assert(II);
    SourceLocation Loc = IdentLoc;
    bool IsInline = false;
    bool IsInvalid = false;
    bool IsStd = false;
    bool AddToKnown = false;
    //Scope *DeclRegionScope = NamespcScope->getParent();

    NamespaceDecl *PrevNS = 0;
    // C++ [namespace.def]p2:
    //   The identifier in an original-namespace-definition shall not
    //   have been previously defined in the declarative region in
    //   which the original-namespace-definition appears. The
    //   identifier in an original-namespace-definition is the name of
    //   the namespace. Subsequently in that declarative region, it is
    //   treated as an original-namespace-name.
    //
    // Since namespace names are unique in their scope, and we don't
    // look through using directives, just look for any ordinary names.

    const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member |
                          Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag |
                          Decl::IDNS_Namespace;
    NamedDecl *PrevDecl = 0;
    DeclContext::lookup_result R = DeclContext->getRedeclContext()->lookup(II);
    for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
            ++I) {
        if ((*I)->getIdentifierNamespace() & IDNS) {
            PrevDecl = *I;
            break;
        }
    }

    PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl);

    if (PrevNS) {
        // This is an extended namespace definition.
        if (IsInline != PrevNS->isInline()) {
//      DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, Loc, II,
//                                      &IsInline, PrevNS);
            assert(false && "need to implement this");
        }
        return PrevNS;
    } else if (PrevDecl) {
        // This is an invalid name redefinition.
        Diag(Loc, diag::err_redefinition_different_kind)
                << II;
        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
        IsInvalid = true;
        // Continue on to push Namespc as current DeclContext and return it.
    } else if (II->isStr("std") &&
               DeclContext->getRedeclContext()->isTranslationUnit()) {
        // This is the first "real" definition of the namespace "std", so update
        // our cache of the "std" namespace to point at this definition.
        PrevNS = getStdNamespace();
        IsStd = true;
        AddToKnown = !IsInline;
    } else {
        // We've seen this namespace for the first time.
        AddToKnown = !IsInline;
    }

    NamespaceDecl *Namespc = NamespaceDecl::Create(Context, DeclContext, IsInline,
                             StartLoc, Loc, II, PrevNS);
    Namespc->IsRogerNamespace = true;

    if (IsInvalid)
        Namespc->setInvalidDecl();

    //ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);

    // FIXME: Should we be merging attributes?
    if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>())
        PushNamespaceVisibilityAttr(Attr, Loc);

    if (IsStd)
        StdNamespace = Namespc;
    if (AddToKnown)
        KnownNamespaces[Namespc] = false;

    DeclContext->addDecl(Namespc);

    if (PrevNS) {
        return PrevNS;
    } else {
        return Namespc;
    }
}
Example #10
0
// N-pass system.
// there's no point counting at this stage.
static void codegenTopLevel(CodegenInstance* cgi, int pass, std::deque<Expr*> expressions, bool isInsideNamespace)
{
	if(pass == 0)
	{
		// add all the types for order-independence -- if we encounter a need, we can
		// force codegen.

		for(Expr* e : expressions)
		{
			NamespaceDecl* ns		= dynamic_cast<NamespaceDecl*>(e);
			TypeAlias* ta			= dynamic_cast<TypeAlias*>(e);
			Struct* str				= dynamic_cast<Struct*>(e);
			Class* cls				= dynamic_cast<Class*>(e);		// enum : class, extension : class
			Func* fn				= dynamic_cast<Func*>(e);
			ForeignFuncDecl* ffi	= dynamic_cast<ForeignFuncDecl*>(e);
			OpOverload* oo			= dynamic_cast<OpOverload*>(e);

			if(ns)					ns->codegenPass(cgi, pass);
			else if(ta)				addTypeToFuncTree(cgi, ta, ta->name, TypeKind::TypeAlias);
			else if(str)			addTypeToFuncTree(cgi, str, str->name, TypeKind::Struct);
			else if(cls)			addTypeToFuncTree(cgi, cls, cls->name, TypeKind::Class);
			else if(fn)				addFuncDeclToFuncTree(cgi, fn->decl);
			else if(ffi)			addFuncDeclToFuncTree(cgi, ffi->decl);
			else if(oo)				addOpOverloadToFuncTree(cgi, oo);
		}
	}
	else if(pass == 1)
	{
		// pass 1: setup extensions
		for(Expr* e : expressions)
		{
			Extension* ext			= dynamic_cast<Extension*>(e);
			NamespaceDecl* ns		= dynamic_cast<NamespaceDecl*>(e);

			if(ext)					ext->mangledName = cgi->mangleWithNamespace(ext->name);
			else if(ns)				ns->codegenPass(cgi, pass);
		}

		// we need the 'Type' enum to be available, as well as the 'Any' type,
		// before any variables are encountered.

		if(!isInsideNamespace)
			TypeInfo::initialiseTypeInfo(cgi);
	}
	else if(pass == 2)
	{
		// pass 2: create types
		for(Expr* e : expressions)
		{
			Struct* str				= dynamic_cast<Struct*>(e);
			Class* cls				= dynamic_cast<Class*>(e);	// enums are handled, since enum : class
			NamespaceDecl* ns		= dynamic_cast<NamespaceDecl*>(e);

			if(str)					str->createType(cgi);
			if(cls)					cls->createType(cgi);
			else if(ns)				ns->codegenPass(cgi, pass);
		}
	}
	else if(pass == 3)
	{
		// pass 3: override types with any extensions
		for(Expr* e : expressions)
		{
			Extension* ext			= dynamic_cast<Extension*>(e);
			NamespaceDecl* ns		= dynamic_cast<NamespaceDecl*>(e);
			TypeAlias* ta			= dynamic_cast<TypeAlias*>(e);

			if(ext)					ext->createType(cgi);
			else if(ta)				ta->createType(cgi);
			else if(ns)				ns->codegenPass(cgi, pass);
		}

		// step 3: generate the type info.
		// now that we have all the types that we need, and they're all fully
		// processed, we create the Type enum.
		TypeInfo::generateTypeInfo(cgi);
	}
	else if(pass == 4)
	{
		// pass 4: create declarations
		for(Expr* e : expressions)
		{
			ForeignFuncDecl* ffi	= dynamic_cast<ForeignFuncDecl*>(e);
			Func* func				= dynamic_cast<Func*>(e);
			NamespaceDecl* ns		= dynamic_cast<NamespaceDecl*>(e);

			if(ffi)					ffi->codegen(cgi);
			else if(ns)				ns->codegenPass(cgi, pass);
			else if(func)
			{
				// func->decl->codegen(cgi);
			}
		}
	}
	else if(pass == 5)
	{
		// start semantic analysis before any typechecking needs to happen.
		SemAnalysis::rewriteDotOperators(cgi);

		// pass 4: everything else
		for(Expr* e : expressions)
		{
			Struct* str				= dynamic_cast<Struct*>(e);
			Class* cls				= dynamic_cast<Class*>(e);		// again, enums are handled since enum : class
			Extension* ext			= dynamic_cast<Extension*>(e);
			NamespaceDecl* ns		= dynamic_cast<NamespaceDecl*>(e);
			VarDecl* vd				= dynamic_cast<VarDecl*>(e);

			if(str)					str->codegen(cgi);
			else if(cls)			cls->codegen(cgi);
			else if(ext)			ext->codegen(cgi);
			else if(ns)				ns->codegenPass(cgi, pass);
			else if(vd)				vd->isGlobal = true, vd->codegen(cgi);
		}
	}
	else if(pass == 6)
	{
		// pass 7: functions. for generic shit.
		for(Expr* e : expressions)
		{
			Func* func						= dynamic_cast<Func*>(e);
			NamespaceDecl* ns				= dynamic_cast<NamespaceDecl*>(e);

			if(func && !func->didCodegen)	func->codegen(cgi);
			if(ns)							ns->codegenPass(cgi, pass);
		}
	}
	else
	{
		error("Invalid pass number '%d'\n", pass);
	}
}
TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {
  auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
      R"(template <class T> struct foo; template<> struct foo<int>{};)",
      R"(template <class T> struct foo; template<> struct foo<signed int>{};)",
      Lang_CXX,
      classTemplateSpecializationDecl());
  auto Spec0 = get<0>(Decls);
  auto Spec1 = get<1>(Decls);
  EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));
}

TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {
  auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
      R"(template <class T> struct foo; template<> struct foo<char>{};)",
      R"(template <class T> struct foo; template<> struct foo<signed char>{};)",
      Lang_CXX,
      classTemplateSpecializationDecl());
  auto Spec0 = get<0>(Decls);
  auto Spec1 = get<1>(Decls);
  EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));
}

TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {
  auto Decls = makeDecls<ClassTemplateSpecializationDecl>(
      R"(
      struct true_type{};
      template <class T> struct foo;
      template<> struct foo<char> : true_type {};
      )",
      R"(
      struct true_type{};
      template <class T> struct foo;
      template<> struct foo<signed char> : true_type {};
      )",
      Lang_CXX,
      classTemplateSpecializationDecl());
  EXPECT_FALSE(testStructuralMatch(Decls));
}

// This test is disabled for now.
// FIXME Enable it, once the check is implemented.
TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {
  auto Code =
      R"(
      namespace NS {
      template <class T> class Base {
          int a;
      };
      class Derived : Base<Derived> {
      };
      }
      void foo(NS::Derived &);
      )";
  auto Decls = makeNamedDecls(Code, Code, Lang_CXX);

  NamespaceDecl *NS =
      LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl());
  ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(
      get<1>(Decls), classTemplateDecl(hasName("Base")));

  // Reorder the decls, move the TD to the last place in the DC.
  NS->removeDecl(TD);
  NS->addDeclInternal(TD);

  EXPECT_FALSE(testStructuralMatch(Decls));
}