Skip to content

Commit

Permalink
Fix Q_NAMESPACE
Browse files Browse the repository at this point in the history
 - Don't generate code for Q_NAMESPACE in a different file
 - Merge namespaces
 - Recurse on nested namespaces
 - paese class info
  • Loading branch information
ogoffart committed Mar 13, 2017
1 parent a100ebf commit 1e07b21
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 19 deletions.
8 changes: 4 additions & 4 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,21 +135,21 @@ struct MocNGASTConsumer : public MocASTConsumer {
}
#endif

void HandleTagDeclDefinition(clang::TagDecl* D) override {
bool shouldParseDecl(clang::Decl * D) override {
// We only want to parse the Qt macro in classes that are in the main file.
auto SL = D->getSourceRange().getBegin();
SL = ci.getSourceManager().getExpansionLoc(SL);
if (ci.getSourceManager().getFileID(SL) != ci.getSourceManager().getMainFileID())
return;
MocASTConsumer::HandleTagDeclDefinition(D);
return false;
return true;
}

void HandleTranslationUnit(clang::ASTContext& Ctx) override {

if (ci.getDiagnostics().hasErrorOccurred())
return;

if (!objects.size()) {
if (!objects.size() && !namespaces.size()) {
ci.getDiagnostics().Report(ci.getSourceManager().getLocForStartOfFile(ci.getSourceManager().getMainFileID()),
ci.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Warning,
"No relevant classes found. No output generated"));
Expand Down
43 changes: 37 additions & 6 deletions src/mocastconsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ void MocASTConsumer::HandleTagDeclDefinition(clang::TagDecl* D)
if (!RD)
return;

if (!shouldParseDecl(D))
return;

clang::ClassTemplateSpecializationDecl* TD = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(RD);
if (TD && TD->getIdentifier() && TD->getName() == "QMetaTypeId" && TD->getTemplateArgs().size() == 1) {
Moc.registered_meta_type.insert(TD->getTemplateArgs().get(0).getAsType()->getCanonicalTypeUnqualified().getTypePtr());
Expand Down Expand Up @@ -90,13 +93,41 @@ bool MocASTConsumer::HandleTopLevelDecl(clang::DeclGroupRef D)
{
for (clang::Decl *Decl : D) {
if (clang::NamespaceDecl *NS = llvm::dyn_cast<clang::NamespaceDecl>(Decl)) {
// Try to find Q_NAMESPACE
NamespaceDef Def = Moc.parseNamespace(NS, ci.getSema());
if (Def.hasQNamespace) {
namespaces.push_back(std::move(Def));
ci.getPreprocessor().enableIncrementalProcessing();
}
if (!shouldParseDecl(Decl))
continue;
HandleNamespaceDefinition(NS);
}
}
return clang::ASTConsumer::HandleTopLevelDecl(D);
}

template<typename T>
static void operator+=(std::vector<T> &v1, const std::vector<T> &v2)
{
v1.insert(v1.end(), v2.begin(), v2.end());
}

void MocASTConsumer::HandleNamespaceDefinition(clang::NamespaceDecl* D)
{
// Try to find Q_NAMESPACE
NamespaceDef Def = Moc.parseNamespace(D, ci.getSema());
if (Def.hasQNamespace) {
auto Canonical = D->getCanonicalDecl();
auto it = std::find_if(namespaces.begin(), namespaces.end(), [&](const NamespaceDef &d)
{ return d.Namespace && d.Namespace->getCanonicalDecl() == Canonical; });
if (it == namespaces.end()) {
namespaces.push_back(std::move(Def));
} else {
// merge the two.
it->Enums += Def.Enums;
it->Extra += Def.Extra;
it->ClassInfo += Def.ClassInfo;
}
ci.getPreprocessor().enableIncrementalProcessing();
}
for (auto it = D->decls_begin(); it != D->decls_end(); ++it) {
if (clang::NamespaceDecl *NS = llvm::dyn_cast<clang::NamespaceDecl>(*it))
HandleNamespaceDefinition(NS);
}
}

9 changes: 7 additions & 2 deletions src/mocastconsumer.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,13 @@ class MocASTConsumer : public clang::ASTConsumer
MocASTConsumer(clang::CompilerInstance &ci) :ci(ci)
{ }

virtual void Initialize(clang::ASTContext& Ctx) override;
void Initialize(clang::ASTContext& Ctx) override;
void HandleTagDeclDefinition(clang::TagDecl* D) override;
virtual bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
bool HandleTopLevelDecl(clang::DeclGroupRef D) override;

virtual bool shouldParseDecl(clang::Decl *D) { return true; }

private:
void HandleNamespaceDefinition(clang::NamespaceDecl *D);
};

21 changes: 14 additions & 7 deletions src/mocng.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,17 @@ static std::pair<clang::StringLiteral*, clang::StringLiteral *> ExtractLiterals(
return {Val1, Val2};
}

static void parseClassInfo(BaseDef &Def, clang::Expr *SubExp, clang::Preprocessor &PP)
{
clang::StringLiteral *Val1 = nullptr, *Val2 = nullptr;
std::tie(Val1, Val2) = ExtractLiterals(SubExp, PP, "Q_CLASSINFO",
"Expected string literal in Q_CLASSINFO");

if (Val1 && Val2) {
Def.ClassInfo.emplace_back(Val1->getString(), Val2->getString());
}
}

static bool IsAnnotationStaticAssert(clang::Decl *Decl, llvm::StringRef *Key, clang::Expr **SubExp) {
if (clang::StaticAssertDecl *S = llvm::dyn_cast<clang::StaticAssertDecl>(Decl)) {
if (auto *E = llvm::dyn_cast<clang::UnaryExprOrTypeTraitExpr>(S->getAssertExpr()))
Expand Down Expand Up @@ -400,13 +411,7 @@ ClassDef MocNg::parseClass(clang::CXXRecordDecl* RD, clang::Sema& Sema)
} else if (key == "qt_qgadget") {
Def.HasQGadget = true;
} else if (key == "qt_classinfo") {
clang::StringLiteral *Val1 = nullptr, *Val2 = nullptr;
std::tie(Val1, Val2) = ExtractLiterals(SubExp, PP, "Q_CLASSINFO",
"Expected string literal in Q_CLASSINFO");

if (Val1 && Val2) {
Def.ClassInfo.emplace_back(Val1->getString(), Val2->getString());
}
parseClassInfo(Def, SubExp, PP);
} else if (key == "qt_interfaces") {
parseInterfaces(Def, SubExp, Sema);
} else if (key == "qt_plugin_metadata") {
Expand Down Expand Up @@ -478,6 +483,8 @@ NamespaceDef MocNg::parseNamespace(clang::NamespaceDecl* ND, clang::Sema& Sema)
parseEnums(Def, ND, false, SubExp, Sema);
} else if (key == "qt_flags") {
parseEnums(Def, ND, true, SubExp, Sema);
} else if (key == "qt_classinfo") {
parseClassInfo(Def, SubExp, Sema.getPreprocessor());
}
}
}
Expand Down

0 comments on commit 1e07b21

Please sign in to comment.