Exemple #1
0
//FIXME.  make it less stupid
static void parseInterfaces(ClassDef &Def, clang::Expr *Content, clang::Sema &Sema) {
    clang::Preprocessor &PP = Sema.getPreprocessor();
    clang::StringLiteral *Val = llvm::dyn_cast<clang::StringLiteral>(Content);
    if (!Val) {
        PP.getDiagnostics().Report(Content->getExprLoc(),
                                   PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
                                                                       "Invalid Q_INTERFACES annotation"));
        return;
    }

    llvm::MemoryBuffer* Buf = maybe_unique(llvm::MemoryBuffer::getMemBufferCopy(Val->getString(), "Q_INTERFACES"));
    clang::Lexer Lex(CreateFileIDForMemBuffer(PP, Buf, Content->getExprLoc()),
                     Buf, PP.getSourceManager(), PP.getLangOpts());

    clang::Token Tok;
    bool Append = false;
    bool Error = false;
    while (true) {
        Lex.LexFromRawLexer(Tok);

        if (Tok.is(clang::tok::eof))
            break;

        if (Tok.is(clang::tok::raw_identifier))
            PP.LookUpIdentifierInfo(Tok);

        if (Tok.is(clang::tok::identifier)) {
            if (Append)
                Def.Interfaces.back() += PP.getSpelling(Tok);
            else
                Def.Interfaces.push_back(PP.getSpelling(Tok));
            Append = false;
            continue;
        }

        if (Append) {
            Error = true;
            break;
        }

        if (Tok.is(clang::tok::coloncolon)) {
            Def.Interfaces.back() += PP.getSpelling(Tok);
            Append = true;
            continue;
        }

        if (!Tok.is(clang::tok::colon)) {
            Error = true;
            break;
        }
    }

     if (Error || Append || !Tok.is(clang::tok::eof)) {
         PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP),
                    PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
                    "parse error in Q_INTERFACES"));
     }

     // TODO: check interface validity
}
Exemple #2
0
void MocASTConsumer::Initialize(clang::ASTContext& Ctx) {
    ctx = &Ctx;
    PPCallbacks = new MocPPCallbacks(ci.getPreprocessor(), Moc.Tags);
    ci.getPreprocessor().addPPCallbacks(maybe_unique(PPCallbacks));
//   ci.getDiagnostics().setClient(new DiagnosticClient(), true);

    // We will enable this when we require Qt >= 5.6.1 and libclang >= 3.8
    // Then we will be able to get rid of qobjectdefs-injected
#if 0
    std::string qtPredefinesBuffer;
    llvm::raw_string_ostream qtPredefines(qtPredefinesBuffer);
    clang::MacroBuilder builder(qtPredefines);
    builder.append("# 1 \"<moc-ng built-in>\" 1");
    builder.defineMacro("QT_ANNOTATE_CLASS(type,...)", "static_assert(sizeof(#__VA_ARGS__),#type);");
    builder.defineMacro("QT_ANNOTATE_CLASS2(type,a1,a2)", "static_assert(sizeof(#a1,#a2),#type);");
    builder.defineMacro("QT_ANNOTATE_FUNCTION(a)", "__attribute__((annotate(#a)))");
    builder.defineMacro("QT_ANNOTATE_ACCESS_SPECIFIER(a)", "__attribute__((annotate(#a)))");
    builder.defineMacro("Q_CLASSINFO(name,value)", "static_assert(sizeof(name,value),\"qt_classinfo\");");
    builder.defineMacro("Q_REVISION(v)", "__attribute__((annotate(\"qt_revision:\" QT_STRINGIFY2(v))))");
    // prepend the Qt defines so the command line argument can override them.
    ci.getPreprocessor().setPredefines(qtPredefines.str() + ci.getPreprocessor().getPredefines());
#endif
}
Exemple #3
0
 virtual void Initialize(clang::ASTContext& Ctx) override {
     annotator.setSourceMgr(Ctx.getSourceManager(), Ctx.getLangOpts());
     annotator.setMangleContext(Ctx.createMangleContext());
     ci.getPreprocessor().addPPCallbacks(maybe_unique(new PreprocessorCallback(annotator, ci.getPreprocessor())));
     ci.getDiagnostics().setClient(new BrowserDiagnosticClient(annotator), true);
 }
Exemple #4
0
static void parseEnums(ClassDef &Def, bool isFlag, clang::Expr *Content, clang::Sema &Sema) {
    clang::Preprocessor &PP = Sema.getPreprocessor();
    clang::StringLiteral *Val = llvm::dyn_cast<clang::StringLiteral>(Content);
    if (!Val) {
        PP.getDiagnostics().Report(Content->getExprLoc(),
                                   PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
                                   "Invalid Q_ENUMS annotation"));
        return;
    }

    llvm::MemoryBuffer* Buf = maybe_unique(llvm::MemoryBuffer::getMemBufferCopy(Val->getString(), "Q_ENUMS"));
    clang::Lexer Lex(CreateFileIDForMemBuffer(PP, Buf, Content->getExprLoc()),
                     Buf, PP.getSourceManager(), PP.getLangOpts());

    clang::CXXScopeSpec SS;
    clang::Token Tok, Next;
    Lex.LexFromRawLexer(Tok);
    for (; !Tok.is(clang::tok::eof); Tok = Next) {
        Lex.LexFromRawLexer(Next);
        clang::IdentifierInfo* II = nullptr;
        if (Tok.is(clang::tok::raw_identifier))
            II = PP.LookUpIdentifierInfo(Tok);


        if (Tok.is(clang::tok::identifier)) {

            if (Next.is(clang::tok::coloncolon)) {
                if (Sema.ActOnCXXNestedNameSpecifier(Sema.getScopeForContext(Def.Record), *II,
                        GetFromLiteral(Tok, Val, PP), GetFromLiteral(Next, Val, PP), {}, false, SS))
                    SS.SetInvalid({GetFromLiteral(Tok, Val, PP), GetFromLiteral(Next, Val, PP)});

                Lex.LexFromRawLexer(Next);
                continue;
            }

            clang::LookupResult Found(Sema, II, GetFromLiteral(Tok, Val, PP), clang::Sema::LookupNestedNameSpecifierName);
            if (SS.isEmpty())
                Sema.LookupQualifiedName(Found, Def.Record);
            else {
                clang::DeclContext* DC = Sema.computeDeclContext(SS);
                Sema.LookupQualifiedName(Found, DC ? DC : Def.Record);
            }

            llvm::StringRef Alias;
            clang::EnumDecl* R = Found.getAsSingle<clang::EnumDecl>();

            if (!R) {
                if (clang::TypedefDecl *TD = Found.getAsSingle<clang::TypedefDecl>()) {
                    const clang::EnumType* ET = TD->getUnderlyingType()->getAs<clang::EnumType>();
                    const clang::TemplateSpecializationType* TDR = TD->getUnderlyingType()->getAs<clang::TemplateSpecializationType>();
                    if(TDR && TDR->getNumArgs() == 1 && TDR->getTemplateName().getAsTemplateDecl()->getName() == "QFlags")
                        ET = TDR->getArg(0).getAsType()->getAs<clang::EnumType>();
                    if (ET) {
                        R = ET->getDecl();
                        if (TD->getIdentifier())
                            Alias = TD->getName();
                    }
                }
            }

            if (Found.empty() || !R) {
                // TODO: typo correction

                // This should be an error, but the official moc do not understand that as an error.
                PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP),
                                           PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Warning,
                                            "no enum names %0")) << Found.getLookupName();
                break;
            }
            if (R->getDeclContext() == Def.Record) {
                if (Alias.empty() && R->getIdentifier())
                    Alias = R->getName();
                Def.addEnum(R, Alias.empty() ? R->getNameAsString() : std::string(Alias), isFlag);
            } else if (R->getDeclContext()->isRecord() &&  llvm::isa<clang::CXXRecordDecl>(R->getDeclContext())) {
                // TODO: check it is a QObject
                Def.addExtra(llvm::cast<clang::CXXRecordDecl>(R->getDeclContext()));
            }
            SS.clear();
            continue;
        } else if (Tok.is(clang::tok::coloncolon)) {
            if (SS.isEmpty()) {
                SS.MakeGlobal(Sema.getASTContext(), GetFromLiteral(Tok, Val, PP));
                continue;
            }
        }

        PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP),
                                       PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
                                       "Invalid token in Q_ENUMS"));
        break;
    }


}
Exemple #5
0
static void parsePluginMetaData(ClassDef &Def, clang::Expr *Content, clang::Sema &Sema) {
    clang::Preprocessor &PP = Sema.getPreprocessor();
    clang::StringLiteral *Val = llvm::dyn_cast<clang::StringLiteral>(Content);
    if (!Val) {
        PP.getDiagnostics().Report(Content->getExprLoc(),
                                   PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
                                                                       "Invalid Q_PLUGIN_METADATA annotation"));
        return;
    }

    llvm::MemoryBuffer* Buf = maybe_unique(llvm::MemoryBuffer::getMemBufferCopy(Val->getString(), "Q_PLUGIN_METADATA"));
    clang::Lexer Lex(CreateFileIDForMemBuffer(PP, Buf, Content->getExprLoc()),
                     Buf, PP.getSourceManager(), PP.getLangOpts());

    clang::Token Tok;
    Lex.LexFromRawLexer(Tok);
    while (Tok.is(clang::tok::raw_identifier)) {
        clang::IdentifierInfo *II =  PP.LookUpIdentifierInfo(Tok);
        if (II->getName() != "IID" && II->getName() != "FILE") {
            Lex.LexFromRawLexer(Tok);
            continue;
        }

        Lex.LexFromRawLexer(Tok);
        if (!Tok.is(clang::tok::string_literal)) {
            PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP),
                        PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
                                                            "Expected string literal"));
            return;
        }

        llvm::SmallVector<clang::Token, 4> StrToks;
        do {
            StrToks.push_back(Tok);
            Lex.LexFromRawLexer(Tok);
        } while (Tok.is(clang::tok::string_literal));
#if CLANG_VERSION_MAJOR!=3 || CLANG_VERSION_MINOR>4
        clang::StringLiteralParser Literal(StrToks, PP);
#else
        clang::StringLiteralParser Literal(&StrToks[0], StrToks.size(), PP);
#endif
        if (Literal.hadError)
            return;

        if (II->getName() == "IID")
            Def.Plugin.IID = Literal.GetString();
        else {
            llvm::StringRef Filename = Literal.GetString();
            const clang::DirectoryLookup *CurDir;
            const clang::FileEntry *File = PP.LookupFile(
#if CLANG_VERSION_MAJOR!=3 || CLANG_VERSION_MINOR>3
                Val->getLocStart(),
#endif
                Filename, false, nullptr,
#if CLANG_VERSION_MAJOR!=3 || CLANG_VERSION_MINOR>5
                nullptr,
#endif
                CurDir, nullptr, nullptr, nullptr);

            if (!File) {
                PP.getDiagnostics().Report(GetFromLiteral(StrToks.front(), Val, PP), clang::diag::err_pp_file_not_found)
                    << Filename;
                return;
            }
            const llvm::MemoryBuffer* JSonBuf = PP.getSourceManager().getMemoryBufferForFile(File);
            llvm::SourceMgr SM;
            llvm::yaml::Stream YAMLStream(JSonBuf->getBuffer(), SM);
            llvm::yaml::document_iterator I = YAMLStream.begin();
            if (I == YAMLStream.end() || !I->getRoot() || !QBJS::Parse(I->getRoot(), Def.Plugin.MetaData)) {
                // FIXME
                PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP),
                                            PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
                                            "Error pwhile parsing JSON"));
                return;
            }
        }
     }

     if (!Tok.is(clang::tok::eof)) {
         PP.getDiagnostics().Report(GetFromLiteral(Tok, Val, PP),
                                    PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error,
                                                                        "Parse error: Expected 'IID' or 'FILE'"));
         return;
     }

}
Exemple #6
0
void MocPPCallbacks::InjectQObjectDefs(clang::SourceLocation Loc) {
#include "qobjectdefs-injected.h"
    auto Buf = maybe_unique(llvm::MemoryBuffer::getMemBuffer(Injected, "qobjectdefs-injected.moc"));
    Loc = PP.getSourceManager().getFileLoc(Loc);
    PP.EnterSourceFile( CreateFileIDForMemBuffer(PP, Buf, Loc), nullptr, Loc);
}