From: Axel Naumann Date: Thu, 18 Sep 2014 20:59:22 +0000 (+0200) Subject: Analyze and fwd declare all dependencies (ROOT-6705 ROOT-6719 ROOT-6712 ROOT-6695). X-Git-Tag: v6-02-00-rc1~59 X-Git-Url: https://root.cern.ch/gitweb?p=root.git;a=commitdiff_plain;h=b0df2b883aa5691ffe122ac4d871c81ddbd7f327 Analyze and fwd declare all dependencies (ROOT-6705 ROOT-6719 ROOT-6712 ROOT-6695). --- diff --git a/core/metautils/src/TMetaUtils.cxx b/core/metautils/src/TMetaUtils.cxx index c22e139..5afb77d 100644 --- a/core/metautils/src/TMetaUtils.cxx +++ b/core/metautils/src/TMetaUtils.cxx @@ -4793,7 +4793,7 @@ const std::string ROOT::TMetaUtils::AST2SourceTools::Decls2FwdDecls(const std::v } std::string newFwdDecl; llvm::raw_string_ostream llvmOstr(newFwdDecl); - interp.forwardDeclare(theTransaction, sema.getSourceManager(), llvmOstr, true, nullptr); + interp.forwardDeclare(theTransaction, sema, llvmOstr, true, nullptr); llvmOstr.flush(); return newFwdDecl; } diff --git a/interpreter/cling/include/cling/Interpreter/Interpreter.h b/interpreter/cling/include/cling/Interpreter/Interpreter.h index 710a655..40f2eba 100644 --- a/interpreter/cling/include/cling/Interpreter/Interpreter.h +++ b/interpreter/cling/include/cling/Interpreter/Interpreter.h @@ -629,7 +629,7 @@ namespace cling { void GenerateAutoloadingMap(llvm::StringRef inFile, llvm::StringRef outFile, bool enableMacros = false, bool enableLogs = true); - void forwardDeclare(Transaction& T, clang::SourceManager& SM, + void forwardDeclare(Transaction& T, clang::Sema& S, llvm::raw_ostream& out, bool enableMacros = false, llvm::raw_ostream* logs = 0) const; diff --git a/interpreter/cling/lib/Interpreter/ForwardDeclPrinter.cpp b/interpreter/cling/lib/Interpreter/ForwardDeclPrinter.cpp index 5e48bbb..269368e 100644 --- a/interpreter/cling/lib/Interpreter/ForwardDeclPrinter.cpp +++ b/interpreter/cling/lib/Interpreter/ForwardDeclPrinter.cpp @@ -10,6 +10,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/Type.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Sema.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -21,12 +22,13 @@ namespace cling { ForwardDeclPrinter::ForwardDeclPrinter(llvm::raw_ostream& OutS, llvm::raw_ostream& LogS, - SourceManager& SM, + Sema& S, const Transaction& T, unsigned Indentation, bool printMacros) : m_Policy(clang::PrintingPolicy(clang::LangOptions())), m_Log(LogS), - m_Indentation(Indentation), m_SMgr(SM), m_SkipFlag(false) { + m_Indentation(Indentation), m_SMgr(S.getSourceManager()), + m_SkipFlag(false) { m_PrintInstantiation = false; m_Policy.SuppressTagKeyword = true; @@ -37,6 +39,11 @@ namespace cling { m_SkipCounter = 0; m_TotalDecls = 0; + llvm::SmallVector builtinNames; + S.getASTContext().BuiltinInfo.GetBuiltinNames(builtinNames); + + m_BuiltinNames.insert(builtinNames.begin(), builtinNames.end()); + // Suppress some unfixable warnings. // TODO: Find proper fix for these issues Out() << "#pragma clang diagnostic ignored \"-Wkeyword-compat\"" << "\n"; @@ -87,7 +94,7 @@ namespace cling { continue; Visit(*dit); - printSemiColon(); + skipCurrentDecl(false); } } @@ -97,29 +104,32 @@ namespace cling { Out() << "#undef " << m << "\n"; } } - - } - - ForwardDeclPrinter::ForwardDeclPrinter(llvm::raw_ostream& OutS, - llvm::raw_ostream& LogS, - clang::SourceManager& SM, - const clang::PrintingPolicy& P, - unsigned Indentation) - : m_Policy(clang::PrintingPolicy(clang::LangOptions())), m_Log(LogS), - m_Indentation(Indentation), m_SMgr(SM), m_SkipFlag(false) { - m_PrintInstantiation = false; - m_Policy.SuppressTagKeyword = true; - m_StreamStack.push(&OutS); } - llvm::raw_ostream& ForwardDeclPrinter::Out() { - return *m_StreamStack.top(); - } - llvm::raw_ostream& ForwardDeclPrinter::Log() { - return m_Log; + void ForwardDeclPrinter::Visit(clang::Decl *D) { + auto Insert = m_Visited.insert(std::pair( + getCanonicalOrNamespace(D), true)); + if (!Insert.second) { + // Already fwd declared or skipped. + if (!Insert.first->second) { + // Already skipped before; notify callers. + skipCurrentDecl(true); + } + return; + } + if (shouldSkip(D)) { + skipCurrentDecl(true); + Insert.first->second = false; + } else { + clang::DeclVisitor::Visit(D); + if (m_SkipFlag) { + // D was not good, flag it. + skipCurrentDecl(true); + Insert.first->second = false; + } + } } - void ForwardDeclPrinter::printDeclType(QualType T, StringRef DeclName, bool Pack) { // Normally, a PackExpansionType is written as T[3]... (for instance, as a // template argument), but if it is the type of a declaration, the ellipsis @@ -137,7 +147,7 @@ namespace cling { return Out(); } - void ForwardDeclPrinter::prettyPrintAttributes(Decl *D, std::string extra) { + void ForwardDeclPrinter::prettyPrintAttributes(Decl *D, std::string extra) { if (D->getSourceRange().isInvalid()) return; @@ -196,27 +206,26 @@ namespace cling { void ForwardDeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { -// VisitDeclContext(D, false); + // VisitDeclContext(D, false); + assert(0 && "ForwardDeclPrinter::VisitTranslationUnitDecl unexpected"); for (auto it = D->decls_begin(); it != D->decls_end(); ++it) { Visit(*it); - printSemiColon(); } } void ForwardDeclPrinter::VisitTypedefDecl(TypedefDecl *D) { - - if (shouldSkip(D)) { - skipCurrentDecl(); + QualType q = D->getTypeSourceInfo()->getType(); + Visit(q); + if (m_SkipFlag) { + skipCurrentDecl(true); return; } - if (!m_Policy.SuppressSpecifiers) { + if (!m_Policy.SuppressSpecifiers) Out() << "typedef "; - if (D->isModulePrivate()) Out() << "__module_private__ "; - } - QualType q = D->getTypeSourceInfo()->getType(); + if (q.isRestrictQualified()){ q.removeLocalRestrict(); q.print(Out(), m_Policy, ""); @@ -226,8 +235,7 @@ namespace cling { q.print(Out(), m_Policy, D->getName()); } prettyPrintAttributes(D); -// Indent() << ";\n"; - skipCurrentDecl(false); + Out() << ";\n"; } void ForwardDeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) { @@ -237,17 +245,11 @@ namespace cling { // return; Out() << "using " << *D; prettyPrintAttributes(D); - Out() << " = " << D->getTypeSourceInfo()->getType().getAsString(m_Policy); -// Indent() << ";\n"; - skipCurrentDecl(false); + Out() << " = " << D->getTypeSourceInfo()->getType().getAsString(m_Policy) + << ";\n"; } void ForwardDeclPrinter::VisitEnumDecl(EnumDecl *D) { - if (shouldSkip(D)) { - skipCurrentDecl(); - return; - } - if (!m_Policy.SuppressSpecifiers && D->isModulePrivate()) Out() << "__module_private__ "; Out() << "enum "; @@ -261,17 +263,7 @@ namespace cling { Out() << *D; // if (D->isFixed()) - Out() << " : " << D->getIntegerType().stream(m_Policy); - - if (D->isCompleteDefinition()) { - for (auto eit = D->decls_begin(), end = D->decls_end() ; - eit != end; ++ eit ){ - if (EnumConstantDecl* ecd = dyn_cast(*eit)){ - VisitEnumConstantDecl(ecd); - } - } - } - skipCurrentDecl(false); + Out() << " : " << D->getIntegerType().stream(m_Policy) << ";\n"; } void ForwardDeclPrinter::VisitRecordDecl(RecordDecl *D) { @@ -280,34 +272,29 @@ namespace cling { Out() << D->getKindName(); prettyPrintAttributes(D); if (D->getIdentifier()) - Out() << ' ' << *D; + Out() << ' ' << *D << ";\n"; // if (D->isCompleteDefinition()) { // Out << " {\n"; // VisitDeclContext(D); // Indent() << "}"; // } - skipCurrentDecl(false); - } - - void ForwardDeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { - m_IncompatibleNames.insert(D->getName()); - //Because enums are forward declared. } void ForwardDeclPrinter::VisitFunctionDecl(FunctionDecl *D) { - if (shouldSkip(D)) { - if (D->getDeclName().isIdentifier()) - m_IncompatibleNames.insert(D->getName()); - skipCurrentDecl(); - return; - } - bool hasTrailingReturn = false; CXXConstructorDecl *CDecl = dyn_cast(D); CXXConversionDecl *ConversionDecl = dyn_cast(D); + Visit(D->getReturnType()); + if (m_SkipFlag) { + skipCurrentDecl(true); + return; + } + + StreamRAII stream(*this); + if (!m_Policy.SuppressSpecifiers) { switch (D->getStorageClass()) { case SC_None: break; @@ -344,17 +331,20 @@ namespace cling { Proto += "("; if (FT) { - llvm::raw_string_ostream POut(Proto); - ForwardDeclPrinter ParamPrinter(POut, m_Log ,m_SMgr, SubPolicy, m_Indentation); + StreamRAII subStream(*this, &SubPolicy); for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { - if (i) POut << ", "; - ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); + if (i) Out() << ", "; + Visit(D->getParamDecl(i)); + if (m_SkipFlag) + skipCurrentDecl(true); + return; } if (FT->isVariadic()) { - if (D->getNumParams()) POut << ", "; - POut << "..."; + if (D->getNumParams()) Out() << ", "; + Out() << "..."; } + Proto += subStream.take(); } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { @@ -507,26 +497,26 @@ namespace cling { // This is a K&R function definition, so we need to print the // parameters. Out() << '\n'; - ForwardDeclPrinter ParamPrinter(Out(), m_Log,m_SMgr, SubPolicy, - m_Indentation); + StreamRAII subStream(*this, &SubPolicy); m_Indentation += m_Policy.Indentation; for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { Indent(); - ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); + Visit(D->getParamDecl(i)); Out() << ";\n"; } m_Indentation -= m_Policy.Indentation; + std::string output = subStream.take(true); + Out() << output; } else Out() << ' '; // D->getBody()->printPretty(Out, 0, SubPolicy, Indentation); } - skipCurrentDecl(false); + Out() << ";\n"; } void ForwardDeclPrinter::VisitFriendDecl(FriendDecl *D) { - skipCurrentDecl(); } void ForwardDeclPrinter::VisitFieldDecl(FieldDecl *D) { @@ -551,21 +541,15 @@ namespace cling { Init->printPretty(Out(), 0, m_Policy, m_Indentation); } prettyPrintAttributes(D); - skipCurrentDecl(false); + Out() << ";\n"; } void ForwardDeclPrinter::VisitLabelDecl(LabelDecl *D) { Out() << *D << ":"; - skipCurrentDecl(false); } void ForwardDeclPrinter::VisitVarDecl(VarDecl *D) { - if(shouldSkip(D)) { - skipCurrentDecl(); - return; - } - if (D->isDefinedOutsideFunctionOrMethod() && D->getStorageClass() != SC_Extern) Out() << "extern "; @@ -654,25 +638,22 @@ namespace cling { } } - skipCurrentDecl(false); + Out() << ";\n"; } void ForwardDeclPrinter::VisitParmVarDecl(ParmVarDecl *D) { VisitVarDecl(D); - skipCurrentDecl(false); } void ForwardDeclPrinter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { Out() << "__asm ("; D->getAsmString()->printPretty(Out(), 0, m_Policy, m_Indentation); - Out() << ")"; - skipCurrentDecl(false); + Out() << ");\n"; } void ForwardDeclPrinter::VisitImportDecl(ImportDecl *D) { Out() << "@import " << D->getImportedModule()->getFullModuleName() << ";\n"; - skipCurrentDecl(false); } void ForwardDeclPrinter::VisitStaticAssertDecl(StaticAssertDecl *D) { @@ -680,8 +661,7 @@ namespace cling { D->getAssertExpr()->printPretty(Out(), 0, m_Policy, m_Indentation); Out() << ", "; D->getMessage()->printPretty(Out(), 0, m_Policy, m_Indentation); - Out() << ")"; - skipCurrentDecl(false); + Out() << ");\n"; } //---------------------------------------------------------------------------- @@ -691,77 +671,72 @@ namespace cling { // VisitDeclContext(D); - std::string output; - llvm::raw_string_ostream stream(output); - m_StreamStack.push(&stream); + bool haveAnyDecl = false; + StreamRAII stream(*this); for (auto dit=D->decls_begin();dit!=D->decls_end();++dit) { Visit(*dit); - printSemiColon(); + haveAnyDecl |= !m_SkipFlag; + skipCurrentDecl(false); } - m_StreamStack.pop(); - stream.flush(); - if ( output.length() == 0 ) { - m_SkipFlag = true; - m_IncompatibleNames.insert(D->getName()); - return; + if (!haveAnyDecl) { + // make sure at least one redecl of this namespace is fwd declared. + if (D == D->getCanonicalDecl()) + haveAnyDecl = true; + } + if (haveAnyDecl) { + if (D->isInline()) + Out() << "inline "; + std::string output = stream.take(true); + Out() << "namespace " << *D << " {\n" << output << "}\n"; } - if (D->isInline()) - Out() << "inline "; - Out() << "namespace " << *D << " {\n" << output << "}\n"; - m_SkipFlag = true; //Don't print a semi after a namespace } void ForwardDeclPrinter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { - - if (shouldSkip(D)) { - skipCurrentDecl(); + Visit(D->getNominatedNamespace()); + if (m_SkipFlag) { + skipCurrentDecl(true); return; } Out() << "using namespace "; if (D->getQualifier()) D->getQualifier()->print(Out(), m_Policy); - Out() << *D->getNominatedNamespaceAsWritten(); - skipCurrentDecl(false); + Out() << *D->getNominatedNamespaceAsWritten() << ";\n"; } void ForwardDeclPrinter::VisitUsingDecl(UsingDecl *D) { - if(shouldSkip(D)){ - skipCurrentDecl(); + // Visit the shadow decls: + for (auto Shadow: D->shadows()) + Visit(Shadow); + + if (m_SkipFlag) { + skipCurrentDecl(true); return; } D->print(Out(),m_Policy); - skipCurrentDecl(false); + Out() << ";\n"; } void ForwardDeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) { - skipCurrentDecl(); + Visit(D->getTargetDecl()); + if (m_SkipFlag) + skipCurrentDecl(true); } void ForwardDeclPrinter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { - if (shouldSkip(D)){ - skipCurrentDecl(); - } } void ForwardDeclPrinter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { Out() << "namespace " << *D << " = "; if (D->getQualifier()) D->getQualifier()->print(Out(), m_Policy); - Out() << *D->getAliasedNamespace(); - skipCurrentDecl(false); + Out() << *D->getAliasedNamespace() << ";\n"; } void ForwardDeclPrinter::VisitEmptyDecl(EmptyDecl *D) { // prettyPrintAttributes(D); - skipCurrentDecl(); } - void ForwardDeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) { - if (shouldSkip(D)) { - skipCurrentDecl(); - return; - } - + void ForwardDeclPrinter::VisitTagDecl(CXXRecordDecl *D) { if (!m_Policy.SuppressSpecifiers && D->isModulePrivate()) Out() << "__module_private__ "; Out() << D->getKindName(); @@ -769,9 +744,7 @@ namespace cling { // if (D->isCompleteDefinition()) prettyPrintAttributes(D); if (D->getIdentifier()) - Out() << ' ' << *D ; - skipCurrentDecl(false); - + Out() << ' ' << *D << ";\n"; } void ForwardDeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { @@ -790,7 +763,6 @@ namespace cling { // VisitDeclContext(D); //To skip weird typedefs and struct definitions for (auto it = D->decls_begin(); it != D->decls_end(); ++it) { Visit(*it); - printSemiColon(); } Out() << "}"; } else { @@ -800,7 +772,7 @@ namespace cling { } } - void ForwardDeclPrinter::PrintTemplateParameters(const TemplateParameterList *Params, + void ForwardDeclPrinter::PrintTemplateParameters(TemplateParameterList *Params, const TemplateArgumentList *Args) { assert(Params); assert(!Args || Params->size() == Args->size()); @@ -811,7 +783,7 @@ namespace cling { if (i != 0) Out() << ", "; - const Decl *Param = Params->getParam(i); + Decl *Param = Params->getParam(i); if (const TemplateTypeParmDecl *TTP = dyn_cast(Param)) { @@ -829,8 +801,7 @@ namespace cling { if (Args) { ArgQT = Args->get(i).getAsType(); } - else if (TTP->hasDefaultArgument() && - !TTP->defaultArgumentWasInherited()) { + else if (TTP->hasDefaultArgument()) { ArgQT = TTP->getDefaultArgument(); } if (!ArgQT.isNull()) { @@ -852,16 +823,15 @@ namespace cling { Out() << " = "; Args->get(i).print(m_Policy, Out()); } - else if (NTTP->hasDefaultArgument() && - !NTTP->defaultArgumentWasInherited()) { + else if (NTTP->hasDefaultArgument()) { Out() << " = "; NTTP->getDefaultArgument()->printPretty(Out(), 0, m_Policy, m_Indentation); } } - else if (const TemplateTemplateParmDecl *TTPD = + else if (TemplateTemplateParmDecl *TTPD = dyn_cast(Param)) { - VisitTemplateDecl(TTPD); + Visit(TTPD); // FIXME: print the default argument, if present. } } @@ -869,29 +839,37 @@ namespace cling { Out() << "> "; } - void ForwardDeclPrinter::VisitTemplateDecl(const TemplateDecl *D) { + void ForwardDeclPrinter::VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl *D) { + + // Find redecl with template default arguments: that's the one + // we want to forward declare. + for (const RedeclarableTemplateDecl* RD: D->redecls()) { + clang::TemplateParameterList* TPL = RD->getTemplateParameters(); + if (TPL->getMinRequiredArguments () < TPL->size()) + D = RD; + } + + StreamRAII Stream(*this); PrintTemplateParameters(D->getTemplateParameters()); if (const TemplateTemplateParmDecl *TTP = dyn_cast(D)) { Out() << "class "; - if (TTP->isParameterPack()) - Out() << "..."; - Out() << D->getName(); + if (TTP->isParameterPack()) + Out() << "..."; + Out() << D->getName(); } else { Visit(D->getTemplatedDecl()); } - skipCurrentDecl(false); + if (!m_SkipFlag) { + std::string output = Stream.take(true); + Out() << output; + } } void ForwardDeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { - if (shouldSkip(D)) { - skipCurrentDecl(); - return; - } - if (m_PrintInstantiation) { TemplateParameterList *Params = D->getTemplateParameters(); for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(), @@ -901,17 +879,11 @@ namespace cling { } } - skipCurrentDecl(false); return VisitRedeclarableTemplateDecl(D); } void ForwardDeclPrinter::VisitClassTemplateDecl(ClassTemplateDecl *D) { - if (shouldSkip(D) ) { - skipCurrentDecl(); - return; - } - if (m_PrintInstantiation) { TemplateParameterList *Params = D->getTemplateParameters(); for (ClassTemplateDecl::spec_iterator I = D->spec_begin(), @@ -921,7 +893,6 @@ namespace cling { Out() << '\n'; } } - skipCurrentDecl(false); return VisitRedeclarableTemplateDecl(D); } @@ -950,49 +921,154 @@ namespace cling { // Out() << ">"; // skipCurrentDecl(false); - skipCurrentDecl(); - //Above code doesn't work properly - //Must find better and more general way to print specializations + Visit(D->getSpecializedTemplate()); + //Above code doesn't work properly + //Must find better and more general way to print specializations } - void ForwardDeclPrinter::printSemiColon(bool flag) { - if (flag) { - if (!m_SkipFlag) - Out() << ";\n"; - else - m_SkipFlag = false; - } - else Out() << ";\n"; - } - bool ForwardDeclPrinter::isIncompatibleType(QualType q, bool includeNNS) { - //FIXME: This is a workaround and filters out many acceptable cases - //Refer to Point#1 - while (q->isAnyPointerType())//For 3 star programmers - q = q->getPointeeType(); - - while (q->isReferenceType())//For move references - q = q.getNonReferenceType(); - - // FIXME: Arrays? everything else? ref to pointer (i.e. combinations)? - - std::string str = QualType(q.getTypePtr(),0).getAsString(); -// llvm::outs() << "Q:"<(q.getTypePtr())) { - NestedNameSpecifier* NNS = ET->getQualifier(); - if (!NNS) { - // suppress TD in typedef struct {...} TD; - result = true; - } else { - if (NNS->getKind() != NestedNameSpecifier::Namespace - && NNS->getKind() != NestedNameSpecifier::Global) - result = true; + void ForwardDeclPrinter::Visit(const Type* typ) { + switch (typ->getTypeClass()) { + +#define VISIT_DECL(WHAT, HOW) \ + case clang::Type::WHAT: \ + Visit(static_cast(typ)->HOW().getTypePtr()); \ + break + VISIT_DECL(ConstantArray, getElementType); + VISIT_DECL(DependentSizedArray, getElementType); + VISIT_DECL(IncompleteArray, getElementType); + VISIT_DECL(VariableArray, getElementType); + VISIT_DECL(Atomic, getValueType); + VISIT_DECL(Auto, getDeducedType); + VISIT_DECL(Decltype, getUnderlyingType); + VISIT_DECL(Paren, getInnerType); + VISIT_DECL(Pointer, getPointeeType); + VISIT_DECL(LValueReference, getPointeeType); + VISIT_DECL(RValueReference, getPointeeType); + VISIT_DECL(TypeOf, getUnderlyingType); + VISIT_DECL(Elaborated, getNamedType); + VISIT_DECL(UnaryTransform, getUnderlyingType); +#undef VISIT_DECL + + case clang::Type::DependentName: + { + VisitNestedNameSpecifier(static_cast(typ) + ->getQualifier()); + } + break; + + case clang::Type::MemberPointer: + { + const MemberPointerType* MPT + = static_cast(typ); + Visit(MPT->getPointeeType().getTypePtr()); + Visit(MPT->getClass()); + } + break; + + case clang::Type::Enum: + // intentional fall-through + case clang::Type::Record: + Visit(static_cast(typ)->getDecl()); + break; + + case clang::Type::TemplateSpecialization: + { + const TemplateSpecializationType* TST + = static_cast(typ); + for (const TemplateArgument& TA: *TST) { + VisitTemplateArgument(TA); } + VisitTemplateName(TST->getTemplateName()); } + break; + + case clang::Type::Typedef: + Visit(static_cast(typ)->getDecl()); + break; + + case clang::Type::TemplateTypeParm: + Visit(static_cast(typ)->getDecl()); + break; + + case clang::Type::Builtin: + // Nothing to do. + break; + case clang::Type::TypeOfExpr: + // Nothing to do. + break; + + default: + Log() << "addDeclsToTransactionForType: Unexpected " + << typ->getTypeClassName() << '\n'; + break; + } + } + + void ForwardDeclPrinter::VisitTemplateArgument(const TemplateArgument& TA) { + switch (TA.getKind()) { + case clang::TemplateArgument::Type: + Visit(TA.getAsType().getTypePtr()); + break; + case clang::TemplateArgument::Declaration: + Visit(TA.getAsDecl()); + break; + case clang::TemplateArgument::Template: // intentional fall-through: + case clang::TemplateArgument::Pack: + VisitTemplateName(TA.getAsTemplateOrTemplatePattern()); + break; + case clang::TemplateArgument::Expression: + // Nothing to fwd declare, hopefully... + break; + default: + Log() << "Visit(Type*): Unexpected TemplateSpecializationType " + << TA.getKind() << '\n'; + break; } - return result; + } + + void ForwardDeclPrinter::VisitTemplateName(const clang::TemplateName& TN) { + switch (TN.getKind()) { + case clang::TemplateName::Template: + Visit(TN.getAsTemplateDecl()); + break; + case clang::TemplateName::QualifiedTemplate: + Visit(TN.getAsQualifiedTemplateName()->getTemplateDecl()); + break; + case clang::TemplateName::DependentTemplate: + VisitNestedNameSpecifier(TN.getAsDependentTemplateName()->getQualifier()); + break; + case clang::TemplateName::SubstTemplateTemplateParm: + VisitTemplateName(TN.getAsSubstTemplateTemplateParm()->getReplacement()); + break; + case clang::TemplateName::SubstTemplateTemplateParmPack: + VisitTemplateArgument(TN.getAsSubstTemplateTemplateParmPack()->getArgumentPack()); + break; + default: + Log() << "VisitTemplateName: Unexpected kind " << TN.getKind() << '\n'; + break; + } + } + + void ForwardDeclPrinter::VisitNestedNameSpecifier( + const clang::NestedNameSpecifier* NNS) { + if (const clang::NestedNameSpecifier* Prefix = NNS->getPrefix()) + VisitNestedNameSpecifier(Prefix); + + switch (NNS->getKind()) { + case clang::NestedNameSpecifier::Namespace: + Visit(NNS->getAsNamespace()); + break; + case clang::NestedNameSpecifier::TypeSpec: // fall-through: + case clang::NestedNameSpecifier::TypeSpecWithTemplate: + Visit(NNS->getAsType()); + break; + default: + Log() << "VisitNestedNameSpecifier: Unexpected kind " + << NNS->getKind() << '\n'; + break; + + }; } bool ForwardDeclPrinter::isOperator(FunctionDecl *D) { @@ -1009,271 +1085,86 @@ namespace cling { return false; } - bool ForwardDeclPrinter::shouldSkip(FunctionDecl *D) { - bool param = false; - //will be true if any of the params turn out to have incompatible types - - for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { - const Type* type = D->getParamDecl(i)->getType().getTypePtr(); - while (type->isReferenceType()) - type = D->getParamDecl(i)->getType().getNonReferenceType().getTypePtr(); - while (type->isPointerType()) - type = type->getPointeeType().getTypePtr(); - - if (const TemplateSpecializationType* tst - = dyn_cast(type)){ - if (m_IncompatibleNames.find - (tst->getTemplateName().getAsTemplateDecl()->getName()) - != m_IncompatibleNames.end()) { - D->printName(Log()); - Log() << " Function : Incompatible Type\n"; - return true; - } - for (unsigned int i = 0; i < tst->getNumArgs(); ++i ) { - const TemplateArgument& arg = tst->getArg(i); - TemplateArgument::ArgKind kind = arg.getKind(); - if (kind == TemplateArgument::ArgKind::Type){ - if (m_IncompatibleNames.find(arg.getAsType().getAsString()) - != m_IncompatibleNames.end()){ - D->printName(Log()); - Log() << D->getName() << " Function : Incompatible Type in template argument list\n"; - return true; - } - } - if (kind == TemplateArgument::ArgKind::Expression) { - //Expr* expr = arg.getAsExpr(); - //TODO: Traverse this expr - } - } - - } - if (isIncompatibleType(D->getParamDecl(i)->getType())){ - D->printName(Log()); - Log() << " Function : Incompatible Type in argument list\n"; - param = true; - } - } - - if (D->getNameAsString().size() == 0 + bool ForwardDeclPrinter::shouldSkipImpl(FunctionDecl *D) { + //FIXME: setDeletedAsWritten can be called from the + //InclusionDiretctive callback. + //Implement that if important functions are marked so. + //Not important, as users do not need hints + //about using Deleted functions + if (D->getIdentifier() == 0 || D->getNameAsString()[0] == '_' || D->getStorageClass() == SC_Static || D->isCXXClassMember() - || isIncompatibleType(D->getReturnType()) - || param || isOperator(D) || D->isDeleted() - || D->isDeletedAsWritten()){ - //FIXME: setDeletedAsWritten can be called from the - //InclusionDiretctive callback. - //Implement that if important functions are marked so. - //Not important, as users do not need hints - //about using Deleted functions - D->printName(Log()); - Log() << " Function : Other\n"; + || D->isDeletedAsWritten()) { return true; } + return false; } - bool ForwardDeclPrinter::shouldSkip(CXXRecordDecl *D) { - return D->getNameAsString().size() == 0; - } - bool ForwardDeclPrinter::shouldSkip(TypedefDecl *D) { - if (const ElaboratedType* ET = - dyn_cast(D->getTypeSourceInfo()->getType().getTypePtr())) { - if (isa(ET->getNamedType())) { - m_IncompatibleNames.insert(D->getName()); - Log() << D->getName() << " Typedef : enum\n"; - return true; - } - if (isa(ET->getNamedType())) { - m_IncompatibleNames.insert(D->getName()); - Log() << D->getName() << " Typedef : struct\n"; - return true; - } - } - - if (const TemplateSpecializationType* tst - = dyn_cast - (D->getTypeSourceInfo()->getType().getTypePtr())){ - for (unsigned int i = 0; i < tst->getNumArgs(); ++i ) { - const TemplateArgument& arg = tst->getArg(i); - if (arg.getKind() == TemplateArgument::ArgKind::Type) - if (m_IncompatibleNames.find(arg.getAsType().getAsString()) - != m_IncompatibleNames.end()){ - m_IncompatibleNames.insert(D->getName()); - Log() << D->getName() << " Typedef : Incompatible Type\n"; - return true; - } - } - } - if (isIncompatibleType(D->getTypeSourceInfo()->getType())) { - m_IncompatibleNames.insert(D->getName()); - Log() << D->getName() << " Typedef : Incompatible Type\n"; - return true; - } - if (D->getUnderlyingType().getTypePtr()->isFunctionPointerType()) { - const FunctionType* ft = - D->getUnderlyingType().getTypePtr() - ->getPointeeType().getTypePtr()->castAs(); - bool result = isIncompatibleType(ft->getReturnType(),false); - if (const FunctionProtoType* fpt = dyn_cast(ft)){ - for (unsigned int i = 0; i < fpt->getNumParams(); ++i){ - result = result || isIncompatibleType(fpt->getParamType(i),false); - if (result){ - m_IncompatibleNames.insert(D->getName()); - Log() << D->getName() << " Typedef : Function Pointer\n"; - return true; - } + bool ForwardDeclPrinter::shouldSkipImpl(FunctionTemplateDecl *D) { + return shouldSkipImpl(D->getTemplatedDecl()); + } - } - } - return false; - } - if (D->getUnderlyingType().getTypePtr()->isFunctionType()){ - const FunctionType* ft =D->getUnderlyingType().getTypePtr() - ->castAs(); - bool result = isIncompatibleType(ft->getReturnType(),false); - if (const FunctionProtoType* fpt = dyn_cast(ft)){ - for (unsigned int i = 0; i < fpt->getNumParams(); ++i){ - result = result || isIncompatibleType(fpt->getParamType(i),false); - if (result){ - m_IncompatibleNames.insert(D->getName()); - Log() << " Typedef : Function Pointer\n"; - return true; - } - } - } - } - //TODO: Lot of logic overlap with above block, make an abstraction - return false; + bool ForwardDeclPrinter::shouldSkipImpl(TagDecl *D) { + return !D->getIdentifier(); } - bool ForwardDeclPrinter::shouldSkip(VarDecl *D) { - if (D->isDefinedOutsideFunctionOrMethod()){ - if (D->isCXXClassMember()){ - Log() << D->getName() <<" Var : Class Member\n"; - return true ; - } - } - bool stc = D->getStorageClass() == SC_Static; - bool inctype = isIncompatibleType(D->getType()); - if (stc) Log() << D->getName() <<" Var : Static\n"; - if (inctype) Log() << D->getName() <<" Var : Incompatible Type\n"; - if (stc || inctype) { - m_IncompatibleNames.insert(D->getName()); + + bool ForwardDeclPrinter::shouldSkipImpl(VarDecl *D) { + if (D->getStorageClass() == SC_Static) { + Log() << D->getName() <<" Var : Static\n"; + m_Visited[D->getCanonicalDecl()] = false; return true; } return false; } - bool ForwardDeclPrinter::shouldSkip(EnumDecl *D) { - if (D->getName().size() == 0){ + + bool ForwardDeclPrinter::shouldSkipImpl(EnumDecl *D) { + if (!D->getIdentifier()){ D->printName(Log()); Log() << "Enum: Empty name\n"; return true; } return false; } + void ForwardDeclPrinter::skipCurrentDecl(bool skip) { - if (skip) { - m_SkipFlag = true; + m_SkipFlag = skip; + if (skip) m_SkipCounter++; - } m_TotalDecls++; } - bool ForwardDeclPrinter::shouldSkip(ClassTemplateSpecializationDecl *D) { - if (llvm::isa(D)) { - //TODO: How to print partial specializations? - return true; - } - const TemplateArgumentList& iargs = D->getTemplateInstantiationArgs(); - for (unsigned int i = 0; i < iargs.size(); ++i) { - const TemplateArgument& arg = iargs[i]; - if (arg.getKind() == TemplateArgument::ArgKind::Type) - if (m_IncompatibleNames.find(arg.getAsType().getAsString()) - !=m_IncompatibleNames.end()) - return true; - } - return false; - } - bool ForwardDeclPrinter::shouldSkip(UsingDirectiveDecl *D) { - std::string str = D->getNominatedNamespace()->getNameAsString(); - bool inctype = m_IncompatibleNames.find(str) != m_IncompatibleNames.end(); - if (inctype) Log() << str <<" Using Directive : Incompatible Type\n"; - return inctype; - } - bool ForwardDeclPrinter::ContainsIncompatibleName(TemplateParameterList* Params){ - for (unsigned i = 0, e = Params->size(); i != e; ++i) { - const Decl *Param = Params->getParam(i); - if (const TemplateTypeParmDecl *TTP = - dyn_cast(Param)) { - if (TTP->hasDefaultArgument() ) { - if (m_IncompatibleNames.find(TTP->getName()) - !=m_IncompatibleNames.end()){ - return true; - } - } - } - if (const NonTypeTemplateParmDecl *NTTP = - dyn_cast(Param)) { - - if (NTTP->hasDefaultArgument() ) { - QualType type = NTTP->getType(); - if (isIncompatibleType(type)){ - return true; - } - Expr* expr = NTTP->getDefaultArgument(); - expr = expr->IgnoreImpCasts(); - if (DeclRefExpr* dre = dyn_cast(expr)){ - std::string str = dre->getDecl()->getQualifiedNameAsString(); - if (str.find("::") != std::string::npos) - return true; // TODO: Find proper solution - } - } - } - } - return false; - } - - bool ForwardDeclPrinter::shouldSkip(ClassTemplateDecl *D) { - if (ContainsIncompatibleName(D->getTemplateParameters()) - || shouldSkip(D->getTemplatedDecl())){ - Log() << D->getName() <<" Class Template : Incompatible Type\n"; - m_IncompatibleNames.insert(D->getName()); - return true; - } - return false; - } - bool ForwardDeclPrinter::shouldSkip(FunctionTemplateDecl* D){ - bool inctype = ContainsIncompatibleName(D->getTemplateParameters()); - bool func = shouldSkip(D->getTemplatedDecl()); - bool hasdef = hasDefaultArgument(D->getTemplatedDecl()); - if (inctype || func || hasdef ) { - if (D->getDeclName().isIdentifier()){ - m_IncompatibleNames.insert(D->getName()); - if (hasdef) Log() << D->getName() << " Function Template : Has default argument\n"; - } + bool ForwardDeclPrinter::shouldSkipImpl(ClassTemplateSpecializationDecl *D) { + if (llvm::isa(D)) { + //TODO: How to print partial specializations? return true; } return false; } - bool ForwardDeclPrinter::shouldSkip(UsingDecl *D) { - if (m_IncompatibleNames.find(D->getName()) - != m_IncompatibleNames.end()) { - Log() << D->getName() <<" Using Decl : Incompatible Type\n"; + bool ForwardDeclPrinter::shouldSkipImpl(UsingDirectiveDecl *D) { + if (shouldSkipImpl(D->getNominatedNamespace())) { + Log() << D->getNameAsString() <<" Using Directive : Incompatible Type\n"; return true; } return false; } - bool ForwardDeclPrinter::shouldSkip(TypeAliasTemplateDecl *D) { - m_IncompatibleNames.insert(D->getName()); + + bool ForwardDeclPrinter::shouldSkipImpl(TypeAliasTemplateDecl *D) { D->printName(Log()); Log() << " TypeAliasTemplateDecl: Always Skipped\n"; return true; } void ForwardDeclPrinter::printStats() { - Log() << m_SkipCounter << " decls skipped out of " << m_TotalDecls << "\n"; + size_t bad = 0; + for (auto&& i: m_Visited) + if (!i.second) + ++bad; + + Log() << bad << " decls skipped out of " << m_Visited.size() << "\n"; } }//end namespace cling diff --git a/interpreter/cling/lib/Interpreter/ForwardDeclPrinter.h b/interpreter/cling/lib/Interpreter/ForwardDeclPrinter.h index b7da8cd..7547a02 100644 --- a/interpreter/cling/lib/Interpreter/ForwardDeclPrinter.h +++ b/interpreter/cling/lib/Interpreter/ForwardDeclPrinter.h @@ -14,23 +14,15 @@ #include "clang/AST/DeclVisitor.h" #include "clang/AST/PrettyPrinter.h" #include "clang/Basic/Specifiers.h" -#include +#include "llvm/ADT/DenseMap.h" #include +#include ///\brief Generates forward declarations for a Decl or Transaction /// by implementing a DeclVisitor /// /// Important Points: -/// 1. Nested name specifiers: Since there doesn't seem to be a way -/// to forward declare B in the following example: -/// class A { class B{};}; -/// We have chosen to skip all declarations using B. -/// This filters out many acceptable types, -/// like when B is defined within a namespace. -/// The fix for this issue dhould go in isIncompatibleType, -/// which currently just searches for "::" in the type name. -/// -/// 2. Function arguments having an EnumConstant as a default value +/// 1. Function arguments having an EnumConstant as a default value /// are printed in the following way: /// enum E {E_a, E_b}; /// void foo(E e = E_b){} @@ -39,13 +31,13 @@ /// void foo(E e = E(1)); /// 1 is the integral value of E_b. /// -/// 3. Decls, in general, are skipped when they depend on things +/// 2. Decls, in general, are skipped when they depend on things /// that were previously skipped. /// The set of strings, m_IncompatibleNames facilitate this. /// Examine the shouldSkip functions to see why specific types /// are skipped. /// -/// 4. Log file: +/// 3. Log file: /// The name of the file depends on the name of the file where /// the forward declarations are written. /// So, fwd.h produces a corresponding fwd.h.skipped, when @@ -77,7 +69,7 @@ namespace clang { class ParmVarDecl; class QualType; class RecordDecl; - class SourceManager; + class Sema; class StaticAssertDecl; class TemplateArgumentList; class TemplateDecl; @@ -106,31 +98,28 @@ namespace cling { bool m_SkipFlag; //False by default, true if current item is not to be printed - std::set m_IncompatibleNames; + llvm::DenseMap m_Visited; // fwd decl success int m_SkipCounter; int m_TotalDecls; + std::stack m_StreamStack; + std::set m_BuiltinNames; + public: ForwardDeclPrinter(llvm::raw_ostream& OutS, llvm::raw_ostream& LogS, - clang::SourceManager& SM, + clang::Sema& S, const Transaction& T, unsigned Indentation = 0, bool printMacros = false); - ForwardDeclPrinter(llvm::raw_ostream& OutS, - llvm::raw_ostream& LogS, - clang::SourceManager& SM, - const clang::PrintingPolicy& P, - unsigned Indentation = 0); - // void VisitDeclContext(clang::DeclContext *DC, bool shouldIndent = true); + void Visit(clang::Decl *D); void VisitTranslationUnitDecl(clang::TranslationUnitDecl *D); void VisitTypedefDecl(clang::TypedefDecl *D); void VisitTypeAliasDecl(clang::TypeAliasDecl *D); void VisitEnumDecl(clang::EnumDecl *D); void VisitRecordDecl(clang::RecordDecl *D); - void VisitEnumConstantDecl(clang::EnumConstantDecl *D); void VisitEmptyDecl(clang::EmptyDecl *D); void VisitFunctionDecl(clang::FunctionDecl *D); void VisitFriendDecl(clang::FriendDecl *D); @@ -146,42 +135,72 @@ namespace cling { void VisitUsingDecl(clang::UsingDecl* D); void VisitUsingShadowDecl(clang::UsingShadowDecl* D); void VisitNamespaceAliasDecl(clang::NamespaceAliasDecl *D); - void VisitCXXRecordDecl(clang::CXXRecordDecl *D); + void VisitTagDecl(clang::CXXRecordDecl *D); void VisitLinkageSpecDecl(clang::LinkageSpecDecl *D); - void VisitTemplateDecl(const clang::TemplateDecl *D); + void VisitRedeclarableTemplateDecl(const clang::RedeclarableTemplateDecl *D); void VisitFunctionTemplateDecl(clang::FunctionTemplateDecl *D); void VisitClassTemplateDecl(clang::ClassTemplateDecl *D); void VisitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl* D); void VisitTypeAliasTemplateDecl(clang::TypeAliasTemplateDecl* D); + + // Not coming from the RecursiveASTVisitor + void Visit(clang::QualType QT) { Visit(QT.getTypePtr()); } + void Visit(const clang::Type* T); + void VisitNestedNameSpecifier(const clang::NestedNameSpecifier* NNS); + void VisitTemplateArgument(const clang::TemplateArgument& TA); + void VisitTemplateName(const clang::TemplateName& TN); + void printDeclType(clang::QualType T, llvm::StringRef DeclName, bool Pack = false); - void PrintTemplateParameters(const clang::TemplateParameterList *Params, + void PrintTemplateParameters(clang::TemplateParameterList *Params, const clang::TemplateArgumentList *Args = 0); void prettyPrintAttributes(clang::Decl *D, std::string extra = ""); - void printSemiColon(bool flag = true); - //if flag is true , m_SkipFlag is obeyed and reset. - - bool isIncompatibleType(clang::QualType q, bool includeNNS = true); bool isOperator(clang::FunctionDecl* D); bool hasDefaultArgument(clang::FunctionDecl* D); - template - bool shouldSkip(DeclT* D){return false;} + bool shouldSkip(clang::Decl* D) { + switch (D->getKind()) { +#define DECL(TYPE, BASE) \ + case clang::Decl::TYPE: return shouldSkip((clang::TYPE##Decl*)D); break; +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" +#undef DECL +#undef ABSTRACT_DECL + } + } - bool shouldSkip(clang::FunctionDecl* D); - bool shouldSkip(clang::CXXRecordDecl* D); - bool shouldSkip(clang::TypedefDecl* D); - bool shouldSkip(clang::VarDecl* D); - bool shouldSkip(clang::EnumDecl* D); - bool shouldSkip(clang::ClassTemplateSpecializationDecl* D); - bool shouldSkip(clang::UsingDecl* D); - bool shouldSkip(clang::UsingShadowDecl* D){return true;} - bool shouldSkip(clang::UsingDirectiveDecl* D); - bool shouldSkip(clang::ClassTemplateDecl* D); - bool shouldSkip(clang::FunctionTemplateDecl* D); - bool shouldSkip(clang::TypeAliasTemplateDecl* D); + std::string getNameIfPossible(clang::Decl* D) { return ""; } + std::string getNameIfPossible(clang::NamedDecl* D) { + return D->getNameAsString(); + } + template bool shouldSkip(T* D) { + // Anything inside DCs except those bwloe cannot be fwd declared. + clang::Decl::Kind DCKind = D->getDeclContext()->getDeclKind(); + if (DCKind != clang::Decl::Namespace + && DCKind != clang::Decl::TranslationUnit + && DCKind != clang::Decl::LinkageSpec) { + Log() << getNameIfPossible(D) <<" Incompatible DeclContext\n"; + skipCurrentDecl(true); + } else { + if (clang::NamedDecl* ND = clang::dyn_cast(D)) { + if (clang::IdentifierInfo* II = ND->getIdentifier()) { + if (m_BuiltinNames.find(II->getNameStart()) != m_BuiltinNames.end() + || !strncmp(II->getNameStart(), "__builtin_", 10)) + skipCurrentDecl(true); + } + } + if (!m_SkipFlag) + skipCurrentDecl(shouldSkipImpl(D)); + } + if (m_SkipFlag) { + // Remember that we have tried to fwd declare this already. + m_Visited.insert(std::pair( + getCanonicalOrNamespace(D), false)); + } + return m_SkipFlag; + } bool ContainsIncompatibleName(clang::TemplateParameterList* Params); @@ -196,10 +215,62 @@ namespace cling { void Print(clang::AccessSpecifier AS); - llvm::raw_ostream& Out(); - llvm::raw_ostream& Log(); + llvm::raw_ostream& Out() { return *m_StreamStack.top(); } + llvm::raw_ostream& Log() { return m_Log; } - std::stack m_StreamStack; + bool shouldSkipImpl(clang::Decl*){return false;} + + bool shouldSkipImpl(clang::FunctionDecl* D); + bool shouldSkipImpl(clang::FunctionTemplateDecl* D); + bool shouldSkipImpl(clang::TagDecl* D); + bool shouldSkipImpl(clang::VarDecl* D); + bool shouldSkipImpl(clang::EnumDecl* D); + bool shouldSkipImpl(clang::ClassTemplateSpecializationDecl* D); + bool shouldSkipImpl(clang::UsingDirectiveDecl* D); + bool shouldSkipImpl(clang::TypeAliasTemplateDecl* D); + bool shouldSkipImpl(clang::EnumConstantDecl* D) { return false; }; + bool haveSkippedBefore(const clang::Decl* D) const { + auto Found = m_Visited.find(getCanonicalOrNamespace(D)); + return (Found != m_Visited.end() && !Found->second); + } + const clang::Decl* getCanonicalOrNamespace(const clang::Decl* D) const { + if (D->getKind() == clang::Decl::Namespace) + return D; + return D->getCanonicalDecl(); + } + const clang::Decl* getCanonicalOrNamespace(const clang::NamespaceDecl* D) const { + return D; + } + + class StreamRAII { + ForwardDeclPrinter& m_pr; + clang::PrintingPolicy m_oldPol; + std::string m_Output; + llvm::raw_string_ostream m_Stream; + bool m_HavePopped; + public: + StreamRAII(ForwardDeclPrinter& pr, clang::PrintingPolicy* pol = 0): + m_pr(pr), m_oldPol(pr.m_Policy), m_Stream(m_Output), + m_HavePopped(false) { + m_pr.m_StreamStack.push(&m_Stream); + if (pol) + m_pr.m_Policy = *pol; + } + ~StreamRAII() { + if (!m_HavePopped) + m_pr.m_StreamStack.pop(); + m_pr.m_Policy = m_oldPol; + } + std::string take(bool pop = false) { + m_Stream.flush(); + if (pop) { + assert(!m_HavePopped && "No popping twice"); + m_HavePopped = true; + m_pr.m_StreamStack.pop(); + } + return m_Output; + } + }; }; } #endif diff --git a/interpreter/cling/lib/Interpreter/Interpreter.cpp b/interpreter/cling/lib/Interpreter/Interpreter.cpp index 6612a9a..c7efd4a 100644 --- a/interpreter/cling/lib/Interpreter/Interpreter.cpp +++ b/interpreter/cling/lib/Interpreter/Interpreter.cpp @@ -1229,11 +1229,11 @@ namespace cling { llvm::raw_fd_ostream log((outFile + ".skipped").str().c_str(), err, llvm::sys::fs::OpenFlags::F_None); log << "Generated for :" << inFile << "\n"; - forwardDeclare(*T, fwdGen.getCI()->getSourceManager(), out, enableMacros, + forwardDeclare(*T, fwdGen.getCI()->getSema(), out, enableMacros, &log); } - void Interpreter::forwardDeclare(Transaction& T, SourceManager& SM, + void Interpreter::forwardDeclare(Transaction& T, Sema& S, llvm::raw_ostream& out, bool enableMacros /*=false*/, llvm::raw_ostream* logs /*=0*/) const { @@ -1241,7 +1241,7 @@ namespace cling { if (!logs) logs = &null; - ForwardDeclPrinter visitor(out, *logs, SM, T); + ForwardDeclPrinter visitor(out, *logs, S, T); visitor.printStats(); // Avoid assertion in the ~IncrementalParser.