Index: cfe/trunk/lib/AST/ASTImporter.cpp =================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp +++ cfe/trunk/lib/AST/ASTImporter.cpp @@ -58,7 +58,7 @@ QualType VisitExtVectorType(const ExtVectorType *T); QualType VisitFunctionNoProtoType(const FunctionNoProtoType *T); QualType VisitFunctionProtoType(const FunctionProtoType *T); - // FIXME: UnresolvedUsingType + QualType VisitUnresolvedUsingType(const UnresolvedUsingType *T); QualType VisitParenType(const ParenType *T); QualType VisitTypedefType(const TypedefType *T); QualType VisitTypeOfExprType(const TypeOfExprType *T); @@ -129,8 +129,8 @@ TemplateParameterList *ImportTemplateParameterList( TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); - TemplateArgumentLoc ImportTemplateArgumentLoc( - const TemplateArgumentLoc &TALoc, bool &Error); + Optional ImportTemplateArgumentLoc( + const TemplateArgumentLoc &TALoc); bool ImportTemplateArguments(const TemplateArgument *FromArgs, unsigned NumFromArgs, SmallVectorImpl &ToArgs); @@ -143,10 +143,12 @@ bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); Decl *VisitDecl(Decl *D); + Decl *VisitEmptyDecl(EmptyDecl *D); Decl *VisitAccessSpecDecl(AccessSpecDecl *D); Decl *VisitStaticAssertDecl(StaticAssertDecl *D); Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); + Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); Decl *VisitTypedefDecl(TypedefDecl *D); Decl *VisitTypeAliasDecl(TypeAliasDecl *D); @@ -172,6 +174,12 @@ Decl *VisitObjCCategoryDecl(ObjCCategoryDecl *D); Decl *VisitObjCProtocolDecl(ObjCProtocolDecl *D); Decl *VisitLinkageSpecDecl(LinkageSpecDecl *D); + Decl *VisitUsingDecl(UsingDecl *D); + Decl *VisitUsingShadowDecl(UsingShadowDecl *D); + Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D); + Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); + Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + ObjCTypeParamList *ImportObjCTypeParamList(ObjCTypeParamList *list); Decl *VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); @@ -569,6 +577,22 @@ return Importer.getToContext().getFunctionType(ToResultType, ArgTypes, ToEPI); } +QualType ASTNodeImporter::VisitUnresolvedUsingType( + const UnresolvedUsingType *T) { + UnresolvedUsingTypenameDecl *ToD = cast_or_null( + Importer.Import(T->getDecl())); + if (!ToD) + return QualType(); + + UnresolvedUsingTypenameDecl *ToPrevD = + cast_or_null( + Importer.Import(T->getDecl()->getPreviousDecl())); + if (!ToPrevD && T->getDecl()->getPreviousDecl()) + return QualType(); + + return Importer.getToContext().getTypeDeclType(ToD, ToPrevD); +} + QualType ASTNodeImporter::VisitParenType(const ParenType *T) { QualType ToInnerType = Importer.Import(T->getInnerType()); if (ToInnerType.isNull()) @@ -1183,9 +1207,8 @@ llvm_unreachable("Invalid template argument kind"); } -TemplateArgumentLoc ASTNodeImporter::ImportTemplateArgumentLoc( - const TemplateArgumentLoc &TALoc, bool &Error) { - Error = false; +Optional +ASTNodeImporter::ImportTemplateArgumentLoc(const TemplateArgumentLoc &TALoc) { TemplateArgument Arg = ImportTemplateArgument(TALoc.getArgument()); TemplateArgumentLocInfo FromInfo = TALoc.getLocInfo(); TemplateArgumentLocInfo ToInfo; @@ -1193,12 +1216,12 @@ Expr *E = Importer.Import(FromInfo.getAsExpr()); ToInfo = TemplateArgumentLocInfo(E); if (!E) - Error = true; + return None; } else if (Arg.getKind() == TemplateArgument::Type) { if (TypeSourceInfo *TSI = Importer.Import(FromInfo.getAsTypeSourceInfo())) ToInfo = TemplateArgumentLocInfo(TSI); else - Error = true; + return None; } else { ToInfo = TemplateArgumentLocInfo( Importer.Import(FromInfo.getTemplateQualifierLoc()), @@ -1288,6 +1311,28 @@ return nullptr; } +Decl *ASTNodeImporter::VisitEmptyDecl(EmptyDecl *D) { + // Import the context of this declaration. + DeclContext *DC = Importer.ImportContext(D->getDeclContext()); + if (!DC) + return nullptr; + + DeclContext *LexicalDC = DC; + if (D->getDeclContext() != D->getLexicalDeclContext()) { + LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); + if (!LexicalDC) + return nullptr; + } + + // Import the location of this declaration. + SourceLocation Loc = Importer.Import(D->getLocation()); + + EmptyDecl *ToD = EmptyDecl::Create(Importer.getToContext(), DC, Loc); + ToD->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToD); + return ToD; +} + Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { TranslationUnitDecl *ToD = Importer.getToContext().getTranslationUnitDecl(); @@ -1422,6 +1467,44 @@ return ToNamespace; } +Decl *ASTNodeImporter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { + // Import the major distinguishing characteristics of this namespace. + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *LookupD; + if (ImportDeclParts(D, DC, LexicalDC, Name, LookupD, Loc)) + return nullptr; + if (LookupD) + return LookupD; + + // NOTE: No any conflict resolution is done for namespace aliases. + + NamespaceDecl *TargetDecl = cast( + Importer.Import(D->getNamespace())); + if (!TargetDecl) + return nullptr; + + IdentifierInfo *ToII = Importer.Import(D->getIdentifier()); + if (!ToII) + return nullptr; + + NestedNameSpecifierLoc ToQLoc = Importer.Import(D->getQualifierLoc()); + if (D->getQualifierLoc() && !ToQLoc) + return nullptr; + + NamespaceAliasDecl *ToD = NamespaceAliasDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getNamespaceLoc()), + Importer.Import(D->getAliasLoc()), ToII, ToQLoc, + Importer.Import(D->getTargetNameLoc()), TargetDecl); + + ToD->setLexicalDeclContext(LexicalDC); + Importer.Imported(D, ToD); + LexicalDC->addDeclInternal(ToD); + + return ToD; +} + Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // Import the major distinguishing characteristics of this typedef. DeclContext *DC, *LexicalDC; @@ -1821,6 +1904,31 @@ } D2 = D2CXX; D2->setAccess(D->getAccess()); + + Importer.Imported(D, D2); + + if (ClassTemplateDecl *FromDescribed = + DCXX->getDescribedClassTemplate()) { + ClassTemplateDecl *ToDescribed = cast_or_null( + Importer.Import(FromDescribed)); + if (!ToDescribed) + return nullptr; + D2CXX->setDescribedClassTemplate(ToDescribed); + + } else if (MemberSpecializationInfo *MemberInfo = + DCXX->getMemberSpecializationInfo()) { + TemplateSpecializationKind SK = + MemberInfo->getTemplateSpecializationKind(); + CXXRecordDecl *FromInst = DCXX->getInstantiatedFromMemberClass(); + CXXRecordDecl *ToInst = + cast_or_null(Importer.Import(FromInst)); + if (FromInst && !ToInst) + return nullptr; + D2CXX->setInstantiationOfMemberClass(ToInst, SK); + D2CXX->getMemberSpecializationInfo()->setPointOfInstantiation( + Importer.Import(MemberInfo->getPointOfInstantiation())); + } + } else { D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, Name.getAsIdentifierInfo()); @@ -2960,6 +3068,176 @@ return ToLinkageSpec; } +Decl *ASTNodeImporter::VisitUsingDecl(UsingDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + DeclarationNameInfo NameInfo(Name, + Importer.Import(D->getNameInfo().getLoc())); + ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); + + UsingDecl *ToUsing = UsingDecl::Create(Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), + NameInfo, D->hasTypename()); + ToUsing->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsing); + Importer.Imported(D, ToUsing); + + if (NamedDecl *FromPattern = + Importer.getFromContext().getInstantiatedFromUsingDecl(D)) { + if (NamedDecl *ToPattern = + dyn_cast_or_null(Importer.Import(FromPattern))) + Importer.getToContext().setInstantiatedFromUsingDecl(ToUsing, ToPattern); + else + return nullptr; + } + + for (UsingShadowDecl *FromShadow : D->shadows()) { + if (UsingShadowDecl *ToShadow = + dyn_cast_or_null(Importer.Import(FromShadow))) + ToUsing->addShadowDecl(ToShadow); + else + // FIXME: We return a nullptr here but the definition is already created + // and available with lookups. How to fix this?.. + return nullptr; + } + return ToUsing; +} + +Decl *ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + UsingDecl *ToUsing = dyn_cast_or_null( + Importer.Import(D->getUsingDecl())); + if (!ToUsing) + return nullptr; + + NamedDecl *ToTarget = dyn_cast_or_null( + Importer.Import(D->getTargetDecl())); + if (!ToTarget) + return nullptr; + + UsingShadowDecl *ToShadow = UsingShadowDecl::Create( + Importer.getToContext(), DC, Loc, ToUsing, ToTarget); + + ToShadow->setLexicalDeclContext(LexicalDC); + ToShadow->setAccess(D->getAccess()); + Importer.Imported(D, ToShadow); + + if (UsingShadowDecl *FromPattern = + Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) { + if (UsingShadowDecl *ToPattern = + dyn_cast_or_null(Importer.Import(FromPattern))) + Importer.getToContext().setInstantiatedFromUsingShadowDecl(ToShadow, + ToPattern); + else + return nullptr; + } + + LexicalDC->addDeclInternal(ToShadow); + + return ToShadow; +} + + +Decl *ASTNodeImporter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + DeclContext *ToComAncestor = Importer.ImportContext(D->getCommonAncestor()); + if (!ToComAncestor) + return nullptr; + + NamespaceDecl *ToNominated = cast_or_null( + Importer.Import(D->getNominatedNamespace())); + if (!ToNominated) + return nullptr; + + UsingDirectiveDecl *ToUsingDir = UsingDirectiveDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getNamespaceKeyLocation()), + Importer.Import(D->getQualifierLoc()), + Importer.Import(D->getIdentLocation()), ToNominated, ToComAncestor); + ToUsingDir->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsingDir); + Importer.Imported(D, ToUsingDir); + + return ToUsingDir; +} + +Decl *ASTNodeImporter::VisitUnresolvedUsingValueDecl( + UnresolvedUsingValueDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc())); + ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); + + UnresolvedUsingValueDecl *ToUsingValue = UnresolvedUsingValueDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, + Importer.Import(D->getEllipsisLoc())); + + Importer.Imported(D, ToUsingValue); + ToUsingValue->setAccess(D->getAccess()); + ToUsingValue->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsingValue); + + return ToUsingValue; +} + +Decl *ASTNodeImporter::VisitUnresolvedUsingTypenameDecl( + UnresolvedUsingTypenameDecl *D) { + DeclContext *DC, *LexicalDC; + DeclarationName Name; + SourceLocation Loc; + NamedDecl *ToD = nullptr; + if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + return nullptr; + if (ToD) + return ToD; + + UnresolvedUsingTypenameDecl *ToUsing = UnresolvedUsingTypenameDecl::Create( + Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getTypenameLoc()), + Importer.Import(D->getQualifierLoc()), Loc, Name, + Importer.Import(D->getEllipsisLoc())); + + Importer.Imported(D, ToUsing); + ToUsing->setAccess(D->getAccess()); + ToUsing->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(ToUsing); + + return ToUsing; +} + + bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, ImportDefinitionKind Kind) { @@ -3537,7 +3815,6 @@ CXXRecordDecl *DTemplated = D->getTemplatedDecl(); // Create the declaration that is being templated. - // Create the declaration that is being templated. CXXRecordDecl *D2Templated = cast_or_null( Importer.Import(DTemplated)); if (!D2Templated) @@ -3644,11 +3921,10 @@ TemplateArgumentListInfo ToTAInfo; auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten(); for (unsigned I = 0, E = ASTTemplateArgs.NumTemplateArgs; I < E; ++I) { - bool Error = false; - auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I], Error); - if (Error) + if (auto ToLoc = ImportTemplateArgumentLoc(ASTTemplateArgs[I])) + ToTAInfo.addArgument(*ToLoc); + else return nullptr; - ToTAInfo.addArgument(ToLoc); } QualType CanonInjType = Importer.Import( @@ -4531,11 +4807,10 @@ TemplateArgumentListInfo *ResInfo = nullptr; if (E->hasExplicitTemplateArgs()) { for (const auto &FromLoc : E->template_arguments()) { - bool Error = false; - TemplateArgumentLoc ToTALoc = ImportTemplateArgumentLoc(FromLoc, Error); - if (Error) + if (auto ToTALoc = ImportTemplateArgumentLoc(FromLoc)) + ToTAInfo.addArgument(*ToTALoc); + else return nullptr; - ToTAInfo.addArgument(ToTALoc); } ResInfo = &ToTAInfo; } Index: cfe/trunk/test/Analysis/cfg-indirect-goto-determinism.cpp =================================================================== --- cfe/trunk/test/Analysis/cfg-indirect-goto-determinism.cpp +++ cfe/trunk/test/Analysis/cfg-indirect-goto-determinism.cpp @@ -0,0 +1,96 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s + +void *target; +int indirectBlockSuccessorDeterminism() { + (void)&&L1; + (void)&&L2; + (void)&&L3; + (void)&&L4; + (void)&&L5; + (void)&&L6; + (void)&&L7; + (void)&&L8; + (void)&&L9; + (void)&&L10; + (void)&&L11; + (void)&&L12; + (void)&&L13; + (void)&&L14; + (void)&&L15; + (void)&&L16; + (void)&&L17; + (void)&&L18; + (void)&&L19; + (void)&&L20; + (void)&&L21; + (void)&&L22; + (void)&&L23; + (void)&&L24; + (void)&&L25; + (void)&&L26; + (void)&&L27; + (void)&&L28; + (void)&&L29; + (void)&&L30; + (void)&&L31; + (void)&&L32; + (void)&&L33; + (void)&&L34; + (void)&&L35; + (void)&&L36; + (void)&&L37; + (void)&&L38; + (void)&&L39; + (void)&&L40; + + goto *target; + L1: + L2: + L3: + L4: + L5: + L6: + L7: + L8: + L9: + L10: + L11: + L12: + L13: + L14: + L15: + L16: + L17: + L18: + L19: + L20: + L21: + L22: + L23: + L24: + L25: + L26: + L27: + L28: + L29: + L30: + L31: + L32: + L33: + L34: + L35: + L36: + L37: + L38: + L39: + L40: + return 0; +} + +// CHECK-LABEL: [B41 (INDIRECT GOTO DISPATCH)] +// CHECK-NEXT: Preds (1): B42 +// CHECK-NEXT: Succs (40): B1 B2 B3 B4 B5 B6 B7 B8 +// CHECK-NEXT: B9 B10 B11 B12 B13 B14 B15 B16 B17 B18 +// CHECK-NEXT: B19 B20 B21 B22 B23 B24 B25 B26 B27 B28 +// CHECK-NEXT: B29 B30 B31 B32 B33 B34 B35 B36 B37 B38 +// CHECK-NEXT: B39 B40