@@ -3248,56 +3248,164 @@ static bool isAncestorDeclContextOf(const DeclContext *DC, const Stmt *S) {
3248
3248
return false ;
3249
3249
}
3250
3250
3251
- static bool hasTypeDeclaredInsideFunction (QualType T, const FunctionDecl *FD) {
3252
- if (T.isNull ())
3251
+ namespace {
3252
+ // / Check if a type has any reference to a declaration that is inside the body
3253
+ // / of a function.
3254
+ // / The \c CheckType(QualType) function should be used to determine
3255
+ // / this property.
3256
+ // /
3257
+ // / The type visitor visits one type object only (not recursive).
3258
+ // / To find all referenced declarations we must discover all type objects until
3259
+ // / the canonical type is reached (walk over typedef and similar objects). This
3260
+ // / is done by loop over all "sugar" type objects. For every such type we must
3261
+ // / check all declarations that are referenced from it. For this check the
3262
+ // / visitor is used. In the visit functions all referenced declarations except
3263
+ // / the one that follows in the sugar chain (if any) must be checked. For this
3264
+ // / check the same visitor is re-used (it has no state-dependent data).
3265
+ // /
3266
+ // / The visit functions have 3 possible return values:
3267
+ // / - True, found a declaration inside \c ParentDC.
3268
+ // / - False, found declarations only outside \c ParentDC and it is not possible
3269
+ // / to find more declarations (the "sugar" chain does not continue).
3270
+ // / - Empty optional value, found no declarations or only outside \c ParentDC,
3271
+ // / but it is possible to find more declarations in the type "sugar" chain.
3272
+ // / The loop over the "sugar" types can be implemented by using type visit
3273
+ // / functions only (call \c CheckType with the desugared type). With the current
3274
+ // / solution no visit function is needed if the type has only a desugared type
3275
+ // / as data.
3276
+ class IsTypeDeclaredInsideVisitor
3277
+ : public TypeVisitor<IsTypeDeclaredInsideVisitor, Optional<bool >> {
3278
+ public:
3279
+ IsTypeDeclaredInsideVisitor (const FunctionDecl *ParentDC)
3280
+ : ParentDC(ParentDC) {}
3281
+
3282
+ bool CheckType (QualType T) {
3283
+ // Check the chain of "sugar" types.
3284
+ // The "sugar" types are typedef or similar types that have the same
3285
+ // canonical type.
3286
+ if (Optional<bool > Res = Visit (T.getTypePtr ()))
3287
+ return *Res;
3288
+ QualType DsT =
3289
+ T.getSingleStepDesugaredType (ParentDC->getParentASTContext ());
3290
+ while (DsT != T) {
3291
+ if (Optional<bool > Res = Visit (DsT.getTypePtr ()))
3292
+ return *Res;
3293
+ T = DsT;
3294
+ DsT = T.getSingleStepDesugaredType (ParentDC->getParentASTContext ());
3295
+ }
3253
3296
return false ;
3297
+ }
3298
+
3299
+ Optional<bool > VisitTagType (const TagType *T) {
3300
+ if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl ()))
3301
+ for (const auto &Arg : Spec->getTemplateArgs ().asArray ())
3302
+ if (checkTemplateArgument (Arg))
3303
+ return true ;
3304
+ return isAncestorDeclContextOf (ParentDC, T->getDecl ());
3305
+ }
3306
+
3307
+ Optional<bool > VisitPointerType (const PointerType *T) {
3308
+ return CheckType (T->getPointeeType ());
3309
+ }
3310
+
3311
+ Optional<bool > VisitReferenceType (const ReferenceType *T) {
3312
+ return CheckType (T->getPointeeTypeAsWritten ());
3313
+ }
3314
+
3315
+ Optional<bool > VisitTypedefType (const TypedefType *T) {
3316
+ const TypedefNameDecl *TD = T->getDecl ();
3317
+ assert (TD);
3318
+ return isAncestorDeclContextOf (ParentDC, TD);
3319
+ }
3320
+
3321
+ Optional<bool > VisitUsingType (const UsingType *T) {
3322
+ if (T->getFoundDecl () &&
3323
+ isAncestorDeclContextOf (ParentDC, T->getFoundDecl ()))
3324
+ return true ;
3325
+
3326
+ return {};
3327
+ }
3328
+
3329
+ Optional<bool >
3330
+ VisitTemplateSpecializationType (const TemplateSpecializationType *T) {
3331
+ for (const auto &Arg : T->template_arguments ())
3332
+ if (checkTemplateArgument (Arg))
3333
+ return true ;
3334
+ // This type is a "sugar" to a record type, it can have a desugared type.
3335
+ return {};
3336
+ }
3337
+
3338
+ Optional<bool > VisitConstantArrayType (const ConstantArrayType *T) {
3339
+ if (T->getSizeExpr () && isAncestorDeclContextOf (ParentDC, T->getSizeExpr ()))
3340
+ return true ;
3341
+
3342
+ return CheckType (T->getElementType ());
3343
+ }
3344
+
3345
+ Optional<bool > VisitVariableArrayType (const VariableArrayType *T) {
3346
+ llvm_unreachable (
3347
+ " Variable array should not occur in deduced return type of a function" );
3348
+ }
3349
+
3350
+ Optional<bool > VisitIncompleteArrayType (const IncompleteArrayType *T) {
3351
+ llvm_unreachable (" Incomplete array should not occur in deduced return type "
3352
+ " of a function" );
3353
+ }
3354
+
3355
+ Optional<bool > VisitDependentArrayType (const IncompleteArrayType *T) {
3356
+ llvm_unreachable (" Dependent array should not occur in deduced return type "
3357
+ " of a function" );
3358
+ }
3359
+
3360
+ private:
3361
+ const DeclContext *const ParentDC;
3254
3362
3255
- auto CheckTemplateArgument = [FD] (const TemplateArgument &Arg) {
3363
+ bool checkTemplateArgument (const TemplateArgument &Arg) {
3256
3364
switch (Arg.getKind ()) {
3365
+ case TemplateArgument::Null:
3366
+ return false ;
3367
+ case TemplateArgument::Integral:
3368
+ return CheckType (Arg.getIntegralType ());
3257
3369
case TemplateArgument::Type:
3258
- return hasTypeDeclaredInsideFunction (Arg.getAsType (), FD );
3370
+ return CheckType (Arg.getAsType ());
3259
3371
case TemplateArgument::Expression:
3260
- return isAncestorDeclContextOf (FD, Arg.getAsExpr ());
3261
- default :
3262
- // FIXME: Handle other argument kinds.
3372
+ return isAncestorDeclContextOf (ParentDC, Arg.getAsExpr ());
3373
+ case TemplateArgument::Declaration:
3374
+ // FIXME: The declaration in this case is not allowed to be in a function?
3375
+ return isAncestorDeclContextOf (ParentDC, Arg.getAsDecl ());
3376
+ case TemplateArgument::NullPtr:
3377
+ // FIXME: The type is not allowed to be in the function?
3378
+ return CheckType (Arg.getNullPtrType ());
3379
+ case TemplateArgument::Pack:
3380
+ for (const auto &PackArg : Arg.getPackAsArray ())
3381
+ if (checkTemplateArgument (PackArg))
3382
+ return true ;
3383
+ return false ;
3384
+ case TemplateArgument::Template:
3385
+ // Templates can not be defined locally in functions.
3386
+ // A template passed as argument can be not in ParentDC.
3387
+ return false ;
3388
+ case TemplateArgument::TemplateExpansion:
3389
+ // Templates can not be defined locally in functions.
3390
+ // A template passed as argument can be not in ParentDC.
3263
3391
return false ;
3264
3392
}
3265
3393
};
3266
-
3267
- if (const auto *RecordT = T->getAs <RecordType>()) {
3268
- const RecordDecl *RD = RecordT->getDecl ();
3269
- assert (RD);
3270
- if (isAncestorDeclContextOf (FD, RD)) {
3271
- assert (RD->getLexicalDeclContext () == RD->getDeclContext ());
3272
- return true ;
3273
- }
3274
- if (const auto *RDTempl = dyn_cast<ClassTemplateSpecializationDecl>(RD))
3275
- if (llvm::count_if (RDTempl->getTemplateArgs ().asArray (),
3276
- CheckTemplateArgument))
3277
- return true ;
3278
- // Note: It is possible that T can be get as both a RecordType and a
3279
- // TemplateSpecializationType.
3280
- }
3281
- if (const auto *TST = T->getAs <TemplateSpecializationType>())
3282
- return llvm::count_if (TST->template_arguments (), CheckTemplateArgument);
3283
-
3284
- return false ;
3285
- }
3394
+ };
3395
+ } // namespace
3286
3396
3287
3397
bool ASTNodeImporter::hasAutoReturnTypeDeclaredInside (FunctionDecl *D) {
3288
3398
QualType FromTy = D->getType ();
3289
3399
const auto *FromFPT = FromTy->getAs <FunctionProtoType>();
3290
3400
assert (FromFPT && " Must be called on FunctionProtoType" );
3291
- if (const AutoType *AutoT = FromFPT->getReturnType ()->getContainedAutoType ())
3292
- return hasTypeDeclaredInsideFunction (AutoT->getDeducedType (), D);
3293
- if (const auto *TypedefT = FromFPT->getReturnType ()->getAs <TypedefType>()) {
3294
- const TypedefNameDecl *TD = TypedefT->getDecl ();
3295
- assert (TD);
3296
- if (isAncestorDeclContextOf (D, TD)) {
3297
- assert (TD->getLexicalDeclContext () == TD->getDeclContext ());
3298
- return true ;
3299
- }
3401
+
3402
+ QualType RetT = FromFPT->getReturnType ();
3403
+ if (isa<AutoType>(RetT.getTypePtr ())) {
3404
+ FunctionDecl *Def = D->getDefinition ();
3405
+ IsTypeDeclaredInsideVisitor Visitor (Def ? Def : D);
3406
+ return Visitor.CheckType (RetT);
3300
3407
}
3408
+
3301
3409
return false ;
3302
3410
}
3303
3411
0 commit comments