static clang::CanQualType getClangBuiltinTypeFromTypedef( clang::Sema &sema, StringRef typedefName) { auto &context = sema.getASTContext(); auto identifier = &context.Idents.get(typedefName); auto found = sema.LookupSingleName(sema.TUScope, identifier, clang::SourceLocation(), clang::Sema::LookupOrdinaryName); auto typedefDecl = dyn_cast_or_null<clang::TypedefDecl>(found); if (!typedefDecl) return {}; auto underlyingTy = context.getCanonicalType(typedefDecl->getUnderlyingType()); if (underlyingTy->getAs<clang::BuiltinType>()) return underlyingTy; return {}; }
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; } }