Пример #1
0
    bool VisitCompoundStmt(CompoundStmt* CS) {
      for(CompoundStmt::body_iterator I = CS->body_begin(), E = CS->body_end();
          I != E; ++I) {
        if (!isa<BinaryOperator>(*I))
          continue;

        const BinaryOperator* BinOp = cast<BinaryOperator>(*I);
        if (isAutoCandidate(BinOp)) {
          ASTContext& C = m_Sema->getASTContext();
          VarDecl* VD 
            = cast<VarDecl>(cast<DeclRefExpr>(BinOp->getLHS())->getDecl());
          TypeSourceInfo* ResTSI = 0;
          TypeSourceInfo* TrivialTSI 
            = C.getTrivialTypeSourceInfo(VD->getType());
          Expr* RHS = BinOp->getRHS();
          m_Sema->DeduceAutoType(TrivialTSI, RHS, ResTSI);
          VD->setTypeSourceInfo(ResTSI);
          VD->setType(ResTSI->getType());
          VD->setInit(RHS);
          Sema::DeclGroupPtrTy VDPtrTy = m_Sema->ConvertDeclToDeclGroup(VD);
          // Transform the AST into a "sane" state. Replace the binary operator
          // with decl stmt, because the binop semantically is a decl with init.
          StmtResult DS = m_Sema->ActOnDeclStmt(VDPtrTy, BinOp->getLocStart(), 
                                                BinOp->getLocEnd());
          assert(!DS.isInvalid() && "Invalid DeclStmt.");
          *I = DS.take();
        }
      }
      return true; // returning false will abort the in-depth traversal.
    }
Пример #2
0
Decl *Sema::ActOnExternalEntityDecl(ASTContext &C, QualType T,
                                    SourceLocation IDLoc, const IdentifierInfo *IDInfo) {
  SourceLocation TypeLoc;
  VarDecl *ArgumentExternal = nullptr;
  if (auto Prev = LookupIdentifier(IDInfo)) {
    auto Quals = getDeclQualifiers(Prev);
    if(Quals.hasAttributeSpec(Qualifiers::AS_external)) {
      Diags.Report(IDLoc, diag::err_duplicate_attr_spec)
        << DeclSpec::getSpecifierName(Qualifiers::AS_external);
      return Prev;
    }

    // apply EXTERNAL to an unused symbol or an argument.
    auto VD = dyn_cast<VarDecl>(Prev);
    if(VD && (VD->isUnusedSymbol() || VD->isArgument()) ) {
      T = VD->getType();
      TypeLoc = VD->getLocation();
      CurContext->removeDecl(VD);
      if(VD->isArgument())
        ArgumentExternal = VD;
    } else {
      DiagnoseRedefinition(IDLoc, IDInfo, Prev);
      return nullptr;
    }
  }
  if(T.isNull())
    T = C.VoidTy;

  DeclarationNameInfo DeclName(IDInfo,IDLoc);
  auto Decl = FunctionDecl::Create(C, ArgumentExternal? FunctionDecl::ExternalArgument :
                                                        FunctionDecl::External,
                                   CurContext, DeclName, T);
  SetFunctionType(Decl, T, TypeLoc, SourceRange()); //FIXME: proper loc, and range
  CurContext->addDecl(Decl);
  if(ArgumentExternal)
    ArgumentExternal->setType(C.getFunctionType(Decl));
  return Decl;
}
Пример #3
0
/// ActOnEndOfTranslationUnit - This is called at the very end of the
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
  assert(DelayedDiagnostics.getCurrentPool() == NULL
         && "reached end of translation unit with a pool attached?");

  // If code completion is enabled, don't perform any end-of-translation-unit
  // work.
  if (PP.isCodeCompletionEnabled())
    return;

  // Only complete translation units define vtables and perform implicit
  // instantiations.
  if (TUKind == TU_Complete) {
    DiagnoseUseOfUnimplementedSelectors();

    // If any dynamic classes have their key function defined within
    // this translation unit, then those vtables are considered "used" and must
    // be emitted.
    for (DynamicClassesType::iterator I = DynamicClasses.begin(ExternalSource),
                                      E = DynamicClasses.end();
         I != E; ++I) {
      assert(!(*I)->isDependentType() &&
             "Should not see dependent types here!");
      if (const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(*I)) {
        const FunctionDecl *Definition = 0;
        if (KeyFunction->hasBody(Definition))
          MarkVTableUsed(Definition->getLocation(), *I, true);
      }
    }

    // If DefinedUsedVTables ends up marking any virtual member functions it
    // might lead to more pending template instantiations, which we then need
    // to instantiate.
    DefineUsedVTables();

    // C++: Perform implicit template instantiations.
    //
    // FIXME: When we perform these implicit instantiations, we do not
    // carefully keep track of the point of instantiation (C++ [temp.point]).
    // This means that name lookup that occurs within the template
    // instantiation will always happen at the end of the translation unit,
    // so it will find some names that should not be found. Although this is
    // common behavior for C++ compilers, it is technically wrong. In the
    // future, we either need to be able to filter the results of name lookup
    // or we need to perform template instantiations earlier.
    PerformPendingInstantiations();
  }

  // Remove file scoped decls that turned out to be used.
  UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(0,
                                                                         true),
                                             UnusedFileScopedDecls.end(),
                              std::bind1st(std::ptr_fun(ShouldRemoveFromUnused),
                                           this)),
                              UnusedFileScopedDecls.end());

  if (TUKind == TU_Prefix) {
    // Translation unit prefixes don't need any of the checking below.
    TUScope = 0;
    return;
  }

  // Check for #pragma weak identifiers that were never declared
  // FIXME: This will cause diagnostics to be emitted in a non-determinstic
  // order!  Iterating over a densemap like this is bad.
  LoadExternalWeakUndeclaredIdentifiers();
  for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
       I = WeakUndeclaredIdentifiers.begin(),
       E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
    if (I->second.getUsed()) continue;

    Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
      << I->first;
  }

  if (LangOpts.CPlusPlus11 &&
      Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle,
                               SourceLocation())
        != DiagnosticsEngine::Ignored)
    CheckDelegatingCtorCycles();

  if (TUKind == TU_Module) {
    // If we are building a module, resolve all of the exported declarations
    // now.
    if (Module *CurrentModule = PP.getCurrentModule()) {
      ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();

      SmallVector<Module *, 2> Stack;
      Stack.push_back(CurrentModule);
      while (!Stack.empty()) {
        Module *Mod = Stack.back();
        Stack.pop_back();

        // Resolve the exported declarations and conflicts.
        // FIXME: Actually complain, once we figure out how to teach the
        // diagnostic client to deal with complaints in the module map at this
        // point.
        ModMap.resolveExports(Mod, /*Complain=*/false);
        ModMap.resolveConflicts(Mod, /*Complain=*/false);

        // Queue the submodules, so their exports will also be resolved.
        for (Module::submodule_iterator Sub = Mod->submodule_begin(),
                                     SubEnd = Mod->submodule_end();
             Sub != SubEnd; ++Sub) {
          Stack.push_back(*Sub);
        }
      }
    }

    // Modules don't need any of the checking below.
    TUScope = 0;
    return;
  }

  // C99 6.9.2p2:
  //   A declaration of an identifier for an object that has file
  //   scope without an initializer, and without a storage-class
  //   specifier or with the storage-class specifier static,
  //   constitutes a tentative definition. If a translation unit
  //   contains one or more tentative definitions for an identifier,
  //   and the translation unit contains no external definition for
  //   that identifier, then the behavior is exactly as if the
  //   translation unit contains a file scope declaration of that
  //   identifier, with the composite type as of the end of the
  //   translation unit, with an initializer equal to 0.
  llvm::SmallSet<VarDecl *, 32> Seen;
  for (TentativeDefinitionsType::iterator
            T = TentativeDefinitions.begin(ExternalSource),
         TEnd = TentativeDefinitions.end();
       T != TEnd; ++T)
  {
    VarDecl *VD = (*T)->getActingDefinition();

    // If the tentative definition was completed, getActingDefinition() returns
    // null. If we've already seen this variable before, insert()'s second
    // return value is false.
    if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD))
      continue;

    if (const IncompleteArrayType *ArrayT
        = Context.getAsIncompleteArrayType(VD->getType())) {
      if (RequireCompleteType(VD->getLocation(),
                              ArrayT->getElementType(),
                              diag::err_tentative_def_incomplete_type_arr)) {
        VD->setInvalidDecl();
        continue;
      }

      // Set the length of the array to 1 (C99 6.9.2p5).
      Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
      llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
      QualType T = Context.getConstantArrayType(ArrayT->getElementType(),
                                                One, ArrayType::Normal, 0);
      VD->setType(T);
    } else if (RequireCompleteType(VD->getLocation(), VD->getType(),
                                   diag::err_tentative_def_incomplete_type))
      VD->setInvalidDecl();

    CheckCompleteVariableDeclaration(VD);

    // Notify the consumer that we've completed a tentative definition.
    if (!VD->isInvalidDecl())
      Consumer.CompleteTentativeDefinition(VD);

  }

  // If there were errors, disable 'unused' warnings since they will mostly be
  // noise.
  if (!Diags.hasErrorOccurred()) {
    // Output warning for unused file scoped decls.
    for (UnusedFileScopedDeclsType::iterator
           I = UnusedFileScopedDecls.begin(ExternalSource),
           E = UnusedFileScopedDecls.end(); I != E; ++I) {
      if (ShouldRemoveFromUnused(this, *I))
        continue;

      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
        const FunctionDecl *DiagD;
        if (!FD->hasBody(DiagD))
          DiagD = FD;
        if (DiagD->isDeleted())
          continue; // Deleted functions are supposed to be unused.
        if (DiagD->isReferenced()) {
          if (isa<CXXMethodDecl>(DiagD))
            Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
                  << DiagD->getDeclName();
          else {
            if (FD->getStorageClassAsWritten() == SC_Static &&
                !FD->isInlineSpecified() &&
                !SourceMgr.isFromMainFile(
                   SourceMgr.getExpansionLoc(FD->getLocation())))
              Diag(DiagD->getLocation(), diag::warn_unneeded_static_internal_decl)
                << DiagD->getDeclName();
            else
              Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
                   << /*function*/0 << DiagD->getDeclName();
          }
        } else {
          Diag(DiagD->getLocation(),
               isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function
                                         : diag::warn_unused_function)
                << DiagD->getDeclName();
        }
      } else {
        const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
        if (!DiagD)
          DiagD = cast<VarDecl>(*I);
        if (DiagD->isReferenced()) {
          Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
                << /*variable*/1 << DiagD->getDeclName();
        } else {
          Diag(DiagD->getLocation(), diag::warn_unused_variable)
                << DiagD->getDeclName();
        }
      }
    }

    if (ExternalSource)
      ExternalSource->ReadUndefinedButUsed(UndefinedButUsed);
    checkUndefinedButUsed(*this);
  }

  if (Diags.getDiagnosticLevel(diag::warn_unused_private_field,
                               SourceLocation())
        != DiagnosticsEngine::Ignored) {
    RecordCompleteMap RecordsComplete;
    RecordCompleteMap MNCComplete;
    for (NamedDeclSetType::iterator I = UnusedPrivateFields.begin(),
         E = UnusedPrivateFields.end(); I != E; ++I) {
      const NamedDecl *D = *I;
      const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext());
      if (RD && !RD->isUnion() &&
          IsRecordFullyDefined(RD, RecordsComplete, MNCComplete)) {
        Diag(D->getLocation(), diag::warn_unused_private_field)
              << D->getDeclName();
      }
    }
  }

  // Check we've noticed that we're no longer parsing the initializer for every
  // variable. If we miss cases, then at best we have a performance issue and
  // at worst a rejects-valid bug.
  assert(ParsingInitForAutoVars.empty() &&
         "Didn't unmark var as having its initializer parsed");

  TUScope = 0;
}
Пример #4
0
C2::Module* C2ModuleLoader::load(const std::string& name) {

    // NOTE: MEMLEAK on Types

    clang::SourceLocation loc;

    if (name == "stdio") {
        Module* stdioMod = new C2::Module("stdio", true, true);
        // int puts(const char* s);
        {
            FunctionDecl* func = new FunctionDecl("puts", loc, true, Type::Int32());
            // TODO correct arg
            QualType QT(new PointerType(Type::Int8()), QUAL_CONST);
            QT->setCanonicalType(QT);
            VarDecl* Arg1 = new VarDecl(VARDECL_PARAM, "s", loc, QT, 0, true);
            Arg1->setType(QT);
            func->addArg(Arg1);
            stdioMod->addSymbol(func);
            // function type
            func->setType(QualType(new FunctionType(func), 0));
        }
        //int printf(const char *format, ...);
        {
            FunctionDecl* func = new FunctionDecl("printf", loc, true, Type::Int32());
            // NOTE: MEMLEAK ON TYPE, this will go away when we remove these dummy protos
            QualType QT(new PointerType(Type::Int8()), QUAL_CONST);
            QT->setCanonicalType(QT);
            VarDecl* Arg1 = new VarDecl(VARDECL_PARAM, "format", loc, QT, 0, true);
            Arg1->setType(QT);
            func->addArg(Arg1);
            func->setVariadic();
            stdioMod->addSymbol(func);
            // function type
            func->setType(QualType(new FunctionType(func), 0));
        }
        //int sprintf(char *str, const char *format, ...);
        {
            FunctionDecl* func = new FunctionDecl("sprintf", loc, true, Type::Int32());
            // NOTE: MEMLEAK ON TYPE, this will go away when we remove these dummy protos
            QualType QT(new PointerType(Type::Int8()), QUAL_CONST);
            QT->setCanonicalType(QT);
            VarDecl* Arg1 = new VarDecl(VARDECL_PARAM, "str", loc, QT, 0, true);
            Arg1->setType(QT);
            func->addArg(Arg1);
            VarDecl* Arg2 = new VarDecl(VARDECL_PARAM, "format", loc, QT, 0, true);
            Arg2->setType(QT);
            func->addArg(Arg2);
            func->setVariadic();
            stdioMod->addSymbol(func);
            // function type
            func->setType(QualType(new FunctionType(func), 0));
        }
        return stdioMod;
    }

    if (name == "string") {
        Module* stringMod = new C2::Module("string", true, true);
        // void *memset(void *s, int c, size_t n);
        {
            QualType VP(new PointerType(Type::Void()));
            VP->setCanonicalType(VP);
            FunctionDecl* func = new FunctionDecl("memset", loc, true, VP);
            // NOTE: MEMLEAK ON TYPE, this will go away when we remove these dummy protos
            VarDecl* Arg1 = new VarDecl(VARDECL_PARAM, "s", loc, VP, 0, true);
            Arg1->setType(VP);
            func->addArg(Arg1);
            VarDecl* Arg2 = new VarDecl(VARDECL_PARAM, "c", loc, Type::Int32(), 0, true);
            Arg2->setType(Type::Int32());
            func->addArg(Arg2);
            // TEMP size_t -> uint32
            VarDecl* Arg3 = new VarDecl(VARDECL_PARAM, "n", loc, Type::UInt32(), 0, true);
            Arg3->setType(Type::UInt32());
            func->addArg(Arg3);
            stringMod->addSymbol(func);
            // function type
            func->setType(QualType(new FunctionType(func), 0));
        }
        return stringMod;

    }

    if (name == "stdlib") {
        Module* stdlibMod = new C2::Module("stdlib", true, true);
        //void exit(int status);
        {
            FunctionDecl* func = new FunctionDecl("exit", loc, true, Type::Void());
            // TODO correct arg
            VarDecl* Arg1 = new VarDecl(VARDECL_PARAM, "status", loc, Type::Int32(), 0, true);
            Arg1->setType(Type::Int32());
            func->addArg(Arg1);
            stdlibMod->addSymbol(func);
            // function type
            func->setType(QualType(new FunctionType(func), 0));
        }
        return stdlibMod;
    }

    if (name == "c2") {
        Module* c2Mod = new C2::Module("c2", true, false);
        // uint64 buildtime
        {
            // make constant, CTC_NONE
            QualType QT = Type::UInt64();
            QT.addConst();
            uint64_t value = time(0);
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, value, false));
            // TODO get error without value if CTC_NONE, CTC_FULL gives out-of-bounds for value 123?!!
            init->setCTC(CTC_NONE); // Don't check range, only type
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "buildtime", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int8 min_int8
        {
            QualType QT = Type::Int8();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, -128, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_int8", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int8 max_int8
        {
            QualType QT = Type::Int8();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 127, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_int8", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint8 min_uint8
        {
            QualType QT = Type::UInt8();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 0, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_uint8", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint8 max_uint8
        {
            QualType QT = Type::UInt8();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 255, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_uint8", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int16 min_int16
        {
            QualType QT = Type::Int16();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, -32768, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_int16", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int16 max_int16
        {
            QualType QT = Type::Int16();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 32767, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_int16", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint16 min_uint16
        {
            QualType QT = Type::UInt16();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 0, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_uint16", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint16 max_uint16
        {
            QualType QT = Type::UInt16();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 65535, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_uint16", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int32 min_int32
        {
            QualType QT = Type::Int32();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, -2147483648, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_int32", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int32 max_int32
        {
            QualType QT = Type::Int32();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 2147483647, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_int32", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint32 min_uint32
        {
            QualType QT = Type::UInt32();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 0, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_uint32", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint32 max_uint32
        {
            QualType QT = Type::UInt32();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 4294967295, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_uint32", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int64 min_int64
        {
            QualType QT = Type::Int64();
            QT.addConst();
            // NOTE: minimum should be -..808, but clang complains about it..
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, -9223372036854775807ll, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_int64", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // int64 max_int64
        {
            QualType QT = Type::Int64();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 9223372036854775807ll, true));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_int64", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint64 min_uint64
        {
            QualType QT = Type::UInt64();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 0, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "min_uint64", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        // uint64 max_uint64
        {
            QualType QT = Type::UInt64();
            QT.addConst();
            Expr* init = new IntegerLiteral(loc, llvm::APInt(64, 18446744073709551615llu, false));
            init->setCTC(CTC_FULL);
            init->setConstant();
            init->setType(QT);
            VarDecl* var = new VarDecl(VARDECL_GLOBAL, "max_uint64", loc, QT, init, true);
            var->setType(QT);
            c2Mod->addSymbol(var);
        }
        return c2Mod;
    }

    return 0;
}
Пример #5
0
void C2ModuleLoader::load(C2::Module* c2Mod) {
    clang::SourceLocation loc;

    AST* ast = new AST("<generated>", false);
    ASTContext& Context = ast->getASTContext();
    ast->setName("c2", loc);
    c2Mod->addAST(ast);

    // uint64 buildtime
    {
        // make constant, CTC_NONE
        QualType QT = Type::UInt64();
        QT.addConst();
        uint64_t value = time(0);
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, value, false));
        // TODO get error without value if CTC_NONE, CTC_FULL gives out-of-bounds for value 123?!!
        init->setCTC(CTC_NONE); // Don't check range, only type
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "buildtime", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int8 min_int8
    {
        QualType QT = Type::Int8();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, -128, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_int8", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int8 max_int8
    {
        QualType QT = Type::Int8();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 127, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_int8", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint8 min_uint8
    {
        QualType QT = Type::UInt8();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 0, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_uint8", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint8 max_uint8
    {
        QualType QT = Type::UInt8();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 255, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_uint8", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int16 min_int16
    {
        QualType QT = Type::Int16();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, -32768, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_int16", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int16 max_int16
    {
        QualType QT = Type::Int16();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 32767, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_int16", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint16 min_uint16
    {
        QualType QT = Type::UInt16();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 0, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_uint16", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint16 max_uint16
    {
        QualType QT = Type::UInt16();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 65535, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_uint16", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int32 min_int32
    {
        QualType QT = Type::Int32();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, -2147483648, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_int32", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int32 max_int32
    {
        QualType QT = Type::Int32();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 2147483647, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_int32", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint32 min_uint32
    {
        QualType QT = Type::UInt32();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 0, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_uint32", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint32 max_uint32
    {
        QualType QT = Type::UInt32();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 4294967295, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_uint32", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int64 min_int64
    {
        QualType QT = Type::Int64();
        QT.addConst();
        // NOTE: minimum should be -..808, but clang complains about it..
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, -9223372036854775807ll, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_int64", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // int64 max_int64
    {
        QualType QT = Type::Int64();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 9223372036854775807ll, true));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_int64", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint64 min_uint64
    {
        QualType QT = Type::UInt64();
        QT.addConst();
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 0, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "min_uint64", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }
    // uint64 max_uint64
    {
        QualType QT = Type::UInt64();
        QT.addConst();
        // NOTE: capped to -1 since APInt is always signed?
        Expr* init = new (Context) IntegerLiteral(loc, llvm::APInt(64, 18446744073709551615llu, false));
        init->setCTC(CTC_FULL);
        init->setConstant();
        init->setType(QT);
        VarDecl* var = new (Context) VarDecl(VARDECL_GLOBAL, "max_uint64", loc, QT, init, true);
        var->setType(QT);
        ast->addVar(var);
        c2Mod->addSymbol(var);
    }

#if 0
    // type c_char int8
    {
        QualType QT = Type::Int8();
        static const char* name = "c_char";
        AliasTypeDecl* T = new (Context) AliasTypeDecl(name, loc, QT, true);
        QualType A = Context.getAliasType(T, QT);
        A->setCanonicalType(QT);
        T->setType(A);
        c2Mod->addSymbol(T);
    }
#endif
    // create C types (depend on target)
    // NOTE: all types are lower-cased!
    for (unsigned i=0; i<sizeof(ctypes)/sizeof(ctypes[0]); i++) {
        QualType QT = ctypes[i].type;
        AliasTypeDecl* T = new (Context) AliasTypeDecl(ctypes[i].name, loc, QT, true);
        QualType A = Context.getAliasType(T, QT);
        A->setCanonicalType(QT);
        T->setType(A);
        ast->addType(T);
        c2Mod->addSymbol(T);
    }
}
Пример #6
0
/// ActOnEndOfTranslationUnit - This is called at the very end of the
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
  
  // Remove functions that turned out to be used.
  UnusedStaticFuncs.erase(std::remove_if(UnusedStaticFuncs.begin(), 
                                         UnusedStaticFuncs.end(), 
                                         std::mem_fun(&FunctionDecl::isUsed)), 
                          UnusedStaticFuncs.end());
  
  while (1) {
    // C++: Perform implicit template instantiations.
    //
    // FIXME: When we perform these implicit instantiations, we do not carefully
    // keep track of the point of instantiation (C++ [temp.point]). This means
    // that name lookup that occurs within the template instantiation will
    // always happen at the end of the translation unit, so it will find
    // some names that should not be found. Although this is common behavior
    // for C++ compilers, it is technically wrong. In the future, we either need
    // to be able to filter the results of name lookup or we need to perform
    // template instantiations earlier.
    PerformPendingImplicitInstantiations();
    
    /// If ProcessPendingClassesWithUnmarkedVirtualMembers ends up marking 
    /// any virtual member functions it might lead to more pending template
    /// instantiations, which is why we need to loop here.
    if (!ProcessPendingClassesWithUnmarkedVirtualMembers())
      break;
  }
  
  // Check for #pragma weak identifiers that were never declared
  // FIXME: This will cause diagnostics to be emitted in a non-determinstic
  // order!  Iterating over a densemap like this is bad.
  for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
       I = WeakUndeclaredIdentifiers.begin(),
       E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
    if (I->second.getUsed()) continue;

    Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
      << I->first;
  }

  if (!CompleteTranslationUnit)
    return;

  // C99 6.9.2p2:
  //   A declaration of an identifier for an object that has file
  //   scope without an initializer, and without a storage-class
  //   specifier or with the storage-class specifier static,
  //   constitutes a tentative definition. If a translation unit
  //   contains one or more tentative definitions for an identifier,
  //   and the translation unit contains no external definition for
  //   that identifier, then the behavior is exactly as if the
  //   translation unit contains a file scope declaration of that
  //   identifier, with the composite type as of the end of the
  //   translation unit, with an initializer equal to 0.
  llvm::SmallSet<VarDecl *, 32> Seen;
  for (unsigned i = 0, e = TentativeDefinitions.size(); i != e; ++i) {
    VarDecl *VD = TentativeDefinitions[i]->getActingDefinition();

    // If the tentative definition was completed, getActingDefinition() returns
    // null. If we've already seen this variable before, insert()'s second
    // return value is false.
    if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD))
      continue;

    if (const IncompleteArrayType *ArrayT
        = Context.getAsIncompleteArrayType(VD->getType())) {
      if (RequireCompleteType(VD->getLocation(),
                              ArrayT->getElementType(),
                              diag::err_tentative_def_incomplete_type_arr)) {
        VD->setInvalidDecl();
        continue;
      }

      // Set the length of the array to 1 (C99 6.9.2p5).
      Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
      llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
      QualType T = Context.getConstantArrayType(ArrayT->getElementType(),
                                                One, ArrayType::Normal, 0);
      VD->setType(T);
    } else if (RequireCompleteType(VD->getLocation(), VD->getType(),
                                   diag::err_tentative_def_incomplete_type))
      VD->setInvalidDecl();

    // Notify the consumer that we've completed a tentative definition.
    if (!VD->isInvalidDecl())
      Consumer.CompleteTentativeDefinition(VD);

  }
  
  // Output warning for unused functions.
  for (std::vector<FunctionDecl*>::iterator
       F = UnusedStaticFuncs.begin(),
       FEnd = UnusedStaticFuncs.end();
       F != FEnd;
       ++F)
    Diag((*F)->getLocation(), diag::warn_unused_function) << (*F)->getDeclName();
  
}
Пример #7
0
/// ActOnEndOfTranslationUnit - This is called at the very end of the
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
  // Only complete translation units define vtables and perform implicit
  // instantiations.
  if (TUKind == TU_Complete) {
    // If any dynamic classes have their key function defined within
    // this translation unit, then those vtables are considered "used" and must
    // be emitted.
    for (DynamicClassesType::iterator I = DynamicClasses.begin(ExternalSource),
                                      E = DynamicClasses.end();
         I != E; ++I) {
      assert(!(*I)->isDependentType() &&
             "Should not see dependent types here!");
      if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(*I)) {
        const FunctionDecl *Definition = 0;
        if (KeyFunction->hasBody(Definition))
          MarkVTableUsed(Definition->getLocation(), *I, true);
      }
    }

    // If DefinedUsedVTables ends up marking any virtual member functions it
    // might lead to more pending template instantiations, which we then need
    // to instantiate.
    DefineUsedVTables();

    // C++: Perform implicit template instantiations.
    //
    // FIXME: When we perform these implicit instantiations, we do not
    // carefully keep track of the point of instantiation (C++ [temp.point]).
    // This means that name lookup that occurs within the template
    // instantiation will always happen at the end of the translation unit,
    // so it will find some names that should not be found. Although this is
    // common behavior for C++ compilers, it is technically wrong. In the
    // future, we either need to be able to filter the results of name lookup
    // or we need to perform template instantiations earlier.
    PerformPendingInstantiations();
  }
  
  // Remove file scoped decls that turned out to be used.
  UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(0, 
                                                                         true),
                                             UnusedFileScopedDecls.end(),
                              std::bind1st(std::ptr_fun(ShouldRemoveFromUnused),
                                           this)),
                              UnusedFileScopedDecls.end());

  if (TUKind == TU_Prefix) {
    // Translation unit prefixes don't need any of the checking below.
    TUScope = 0;
    return;
  }

  // Check for #pragma weak identifiers that were never declared
  // FIXME: This will cause diagnostics to be emitted in a non-determinstic
  // order!  Iterating over a densemap like this is bad.
  LoadExternalWeakUndeclaredIdentifiers();
  for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
       I = WeakUndeclaredIdentifiers.begin(),
       E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
    if (I->second.getUsed()) continue;

    Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
      << I->first;
  }

  if (TUKind == TU_Module) {
    // Mark any macros from system headers (in /usr/include) as exported, along
    // with our own Clang headers.
    // FIXME: This is a gross hack to deal with the fact that system headers
    // are #include'd in many places within module headers, but are not 
    // themselves modularized. This doesn't actually work, but it lets us
    // focus on other issues for the moment.
    for (Preprocessor::macro_iterator M = PP.macro_begin(false),
                                   MEnd = PP.macro_end(false);
         M != MEnd; ++M) {
      if (M->second && 
          !M->second->isExported() &&
          !M->second->isBuiltinMacro()) {
        SourceLocation Loc = M->second->getDefinitionLoc();
        if (SourceMgr.isInSystemHeader(Loc)) {
          const FileEntry *File
            = SourceMgr.getFileEntryForID(SourceMgr.getFileID(Loc));
          if (File && 
              ((StringRef(File->getName()).find("lib/clang") 
                  != StringRef::npos) ||
               (StringRef(File->getName()).find("usr/include") 
                  != StringRef::npos) ||
               (StringRef(File->getName()).find("usr/local/include") 
                  != StringRef::npos)))
            M->second->setExportLocation(Loc);
        }
      }
    }
          
    // Modules don't need any of the checking below.
    TUScope = 0;
    return;
  }
  
  // C99 6.9.2p2:
  //   A declaration of an identifier for an object that has file
  //   scope without an initializer, and without a storage-class
  //   specifier or with the storage-class specifier static,
  //   constitutes a tentative definition. If a translation unit
  //   contains one or more tentative definitions for an identifier,
  //   and the translation unit contains no external definition for
  //   that identifier, then the behavior is exactly as if the
  //   translation unit contains a file scope declaration of that
  //   identifier, with the composite type as of the end of the
  //   translation unit, with an initializer equal to 0.
  llvm::SmallSet<VarDecl *, 32> Seen;
  for (TentativeDefinitionsType::iterator 
            T = TentativeDefinitions.begin(ExternalSource),
         TEnd = TentativeDefinitions.end();
       T != TEnd; ++T) 
  {
    VarDecl *VD = (*T)->getActingDefinition();

    // If the tentative definition was completed, getActingDefinition() returns
    // null. If we've already seen this variable before, insert()'s second
    // return value is false.
    if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD))
      continue;

    if (const IncompleteArrayType *ArrayT
        = Context.getAsIncompleteArrayType(VD->getType())) {
      if (RequireCompleteType(VD->getLocation(),
                              ArrayT->getElementType(),
                              diag::err_tentative_def_incomplete_type_arr)) {
        VD->setInvalidDecl();
        continue;
      }

      // Set the length of the array to 1 (C99 6.9.2p5).
      Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
      llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
      QualType T = Context.getConstantArrayType(ArrayT->getElementType(),
                                                One, ArrayType::Normal, 0);
      VD->setType(T);
    } else if (RequireCompleteType(VD->getLocation(), VD->getType(),
                                   diag::err_tentative_def_incomplete_type))
      VD->setInvalidDecl();

    // Notify the consumer that we've completed a tentative definition.
    if (!VD->isInvalidDecl())
      Consumer.CompleteTentativeDefinition(VD);

  }

  if (LangOpts.CPlusPlus0x &&
      Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle,
                               SourceLocation())
        != DiagnosticsEngine::Ignored)
    CheckDelegatingCtorCycles();

  // If there were errors, disable 'unused' warnings since they will mostly be
  // noise.
  if (!Diags.hasErrorOccurred()) {
    // Output warning for unused file scoped decls.
    for (UnusedFileScopedDeclsType::iterator
           I = UnusedFileScopedDecls.begin(ExternalSource),
           E = UnusedFileScopedDecls.end(); I != E; ++I) {
      if (ShouldRemoveFromUnused(this, *I))
        continue;
      
      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
        const FunctionDecl *DiagD;
        if (!FD->hasBody(DiagD))
          DiagD = FD;
        if (DiagD->isDeleted())
          continue; // Deleted functions are supposed to be unused.
        if (DiagD->isReferenced()) {
          if (isa<CXXMethodDecl>(DiagD))
            Diag(DiagD->getLocation(), diag::warn_unneeded_member_function)
                  << DiagD->getDeclName();
          else
            Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
                  << /*function*/0 << DiagD->getDeclName();
        } else {
          Diag(DiagD->getLocation(),
               isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function
                                         : diag::warn_unused_function)
                << DiagD->getDeclName();
        }
      } else {
        const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition();
        if (!DiagD)
          DiagD = cast<VarDecl>(*I);
        if (DiagD->isReferenced()) {
          Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl)
                << /*variable*/1 << DiagD->getDeclName();
        } else {
          Diag(DiagD->getLocation(), diag::warn_unused_variable)
                << DiagD->getDeclName();
        }
      }
    }

    checkUndefinedInternals(*this);
  }

  // Check we've noticed that we're no longer parsing the initializer for every
  // variable. If we miss cases, then at best we have a performance issue and
  // at worst a rejects-valid bug.
  assert(ParsingInitForAutoVars.empty() &&
         "Didn't unmark var as having its initializer parsed");

  TUScope = 0;
}
Пример #8
0
  ASTNodeInfo EvaluateTSynthesizer::VisitDeclStmt(DeclStmt* Node) {
    // Visit all the children, which are the contents of the DeclGroupRef
    for (Stmt::child_iterator
           I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
      if (*I) {
        Expr* E = cast_or_null<Expr>(*I);
        if (!E || !IsArtificiallyDependent(E))
          continue;
        //FIXME: don't assume there is only one decl.
        assert(Node->isSingleDecl() && "There is more that one decl in stmt");
        VarDecl* CuredDecl = cast_or_null<VarDecl>(Node->getSingleDecl());
        assert(CuredDecl && "Not a variable declaration!");
        QualType CuredDeclTy = CuredDecl->getType();
        // check if the case is sometype * somevar = init;
        // or some_builtin_type somevar = init;
        if (CuredDecl->hasInit() && (CuredDeclTy->isAnyPointerType()
                                     || !CuredDeclTy->isRecordType())) {
          *I = SubstituteUnknownSymbol(CuredDeclTy, CuredDecl->getInit());
          continue;
        }

        // 1. Check whether this is the case of MyClass A(dep->symbol())
        // 2. Insert the RuntimeUniverse's LifetimeHandler instance
        // 3. Change the A's initializer to *(MyClass*)instance.getMemory()
        // 4. Make A reference (&A)
        // 5. Set the new initializer of A
        if (CuredDeclTy->isLValueReferenceType())
          continue;

        // Set Sema's Current DeclContext to the one we need
        DeclContext* OldDC = m_Sema->CurContext;
        m_Sema->CurContext = CuredDecl->getDeclContext();

        ASTNodeInfo NewNode;
        // 2.1 Get unique name for the LifetimeHandler instance and
        // initialize it
        std::string UniqueName;
        createUniqueName(UniqueName);
        IdentifierInfo& II = m_Context->Idents.get(UniqueName);

        // Prepare the initialization Exprs.
        // We want to call LifetimeHandler(DynamicExprInfo* ExprInfo,
        //                                 DeclContext DC,
        //                                 const char* type)
        //                                 Interpreter* interp)
        llvm::SmallVector<Expr*, 4> Inits;
        // Add MyClass in LifetimeHandler unique(DynamicExprInfo* ExprInfo
        //                                       DC,
        //                                       "MyClass"
        //                                       Interpreter* Interp)
        // Build Arg0 DynamicExprInfo
        Inits.push_back(BuildDynamicExprInfo(E));
        // Build Arg1 DeclContext* DC
        QualType DCTy = m_Context->getTypeDeclType(m_DeclContextDecl);
        Inits.push_back(utils::Synthesize::CStyleCastPtrExpr(m_Sema, DCTy,
                                                     (uint64_t)m_CurDeclContext)
                        );
        // Build Arg2 llvm::StringRef
        // Get the type of the type without specifiers
        PrintingPolicy Policy(m_Context->getLangOpts());
        Policy.SuppressTagKeyword = 1;
        std::string Res;
        CuredDeclTy.getAsStringInternal(Res, Policy);
        Inits.push_back(ConstructConstCharPtrExpr(Res.c_str()));

        // Build Arg3 cling::Interpreter
        CXXScopeSpec CXXSS;
        DeclarationNameInfo NameInfo(m_gCling->getDeclName(), 
                                     m_gCling->getLocStart());
        Expr* gClingDRE 
          = m_Sema->BuildDeclarationNameExpr(CXXSS, NameInfo ,m_gCling).take();
        Inits.push_back(gClingDRE);
        
        // 2.3 Create a variable from LifetimeHandler.
        QualType HandlerTy = m_Context->getTypeDeclType(m_LifetimeHandlerDecl);
        TypeSourceInfo* TSI = m_Context->getTrivialTypeSourceInfo(HandlerTy,
                                                                  m_NoSLoc);
        VarDecl* HandlerInstance = VarDecl::Create(*m_Context,
                                                   CuredDecl->getDeclContext(),
                                                   m_NoSLoc,
                                                   m_NoSLoc,
                                                   &II,
                                                   HandlerTy,
                                                   TSI,
                                                   SC_None);
        
        // 2.4 Call the best-match constructor. The method does overload
        // resolution of the constructors and then initializes the new
        // variable with it
        ExprResult InitExprResult
          = m_Sema->ActOnParenListExpr(m_NoSLoc,
                                       m_NoELoc,
                                       Inits);
        m_Sema->AddInitializerToDecl(HandlerInstance,
                                     InitExprResult.take(),
                                     /*DirectInit*/ true,
                                     /*TypeMayContainAuto*/ false);
        
        // 2.5 Register the instance in the enclosing context
        CuredDecl->getDeclContext()->addDecl(HandlerInstance);
        NewNode.addNode(new (m_Context)
                        DeclStmt(DeclGroupRef(HandlerInstance),
                                 m_NoSLoc,
                                 m_NoELoc)
                        );
        
        // 3.1 Build a DeclRefExpr, which holds the object
        DeclRefExpr* MemberExprBase
          = m_Sema->BuildDeclRefExpr(HandlerInstance,
                                     HandlerTy,
                                     VK_LValue,
                                     m_NoSLoc
                                     ).takeAs<DeclRefExpr>();
        // 3.2 Create a MemberExpr to getMemory from its declaration.
        CXXScopeSpec SS;
        LookupResult MemberLookup(*m_Sema, m_LHgetMemoryDecl->getDeclName(),
                                  m_NoSLoc, Sema::LookupMemberName);
        // Add the declaration as if doesn't exist.
        // TODO: Check whether this is the most appropriate variant
        MemberLookup.addDecl(m_LHgetMemoryDecl, AS_public);
        MemberLookup.resolveKind();
        Expr* MemberExpr = m_Sema->BuildMemberReferenceExpr(MemberExprBase,
                                                            HandlerTy,
                                                            m_NoSLoc,
                                                            /*IsArrow=*/false,
                                                            SS,
                                                            m_NoSLoc,
                                                     /*FirstQualifierInScope=*/0,
                                                            MemberLookup,
                                                            /*TemplateArgs=*/0
                                                            ).take();
        // 3.3 Build the actual call
        Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
        Expr* theCall = m_Sema->ActOnCallExpr(S,
                                              MemberExpr,
                                              m_NoSLoc,
                                              MultiExprArg(),
                                              m_NoELoc).take();
        // Cast to the type LHS type
        Expr* Result 
          = utils::Synthesize::CStyleCastPtrExpr(m_Sema, CuredDeclTy, theCall);
        // Cast once more (dereference the cstyle cast)
        Result = m_Sema->BuildUnaryOp(S, m_NoSLoc, UO_Deref, Result).take();
        // 4.
        CuredDecl->setType(m_Context->getLValueReferenceType(CuredDeclTy));
        // 5.
        CuredDecl->setInit(Result);

        NewNode.addNode(Node);

        // Restore Sema's original DeclContext
        m_Sema->CurContext = OldDC;
        return NewNode;
      }
    }
    return ASTNodeInfo(Node, 0);
  }