@@ -2232,6 +2232,191 @@ TEST_P(ImportFunctions,
2232
2232
}).match (ToTU, functionDecl ()));
2233
2233
}
2234
2234
2235
+ TEST_P (ImportFunctions, ImportOverriddenMethodTwice) {
2236
+ auto Code =
2237
+ R"(
2238
+ struct B { virtual void f(); };
2239
+ struct D:B { void f(); };
2240
+ )" ;
2241
+ auto BFP =
2242
+ cxxMethodDecl (hasName (" f" ), hasParent (cxxRecordDecl (hasName (" B" ))));
2243
+ auto DFP =
2244
+ cxxMethodDecl (hasName (" f" ), hasParent (cxxRecordDecl (hasName (" D" ))));
2245
+
2246
+ Decl *FromTU0 = getTuDecl (Code, Lang_CXX);
2247
+ auto *DF = FirstDeclMatcher<CXXMethodDecl>().match (FromTU0, DFP);
2248
+ Import (DF, Lang_CXX);
2249
+
2250
+ Decl *FromTU1 = getTuDecl (Code, Lang_CXX, " input1.cc" );
2251
+ auto *BF = FirstDeclMatcher<CXXMethodDecl>().match (FromTU1, BFP);
2252
+ Import (BF, Lang_CXX);
2253
+
2254
+ auto *ToTU = ToAST->getASTContext ().getTranslationUnitDecl ();
2255
+
2256
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, BFP), 1u );
2257
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, DFP), 1u );
2258
+ }
2259
+
2260
+ TEST_P (ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2261
+ auto CodeWithoutDef =
2262
+ R"(
2263
+ struct B { virtual void f(); };
2264
+ struct D:B { void f(); };
2265
+ )" ;
2266
+ auto CodeWithDef =
2267
+ R"(
2268
+ struct B { virtual void f(){}; };
2269
+ struct D:B { void f(){}; };
2270
+ )" ;
2271
+ auto BFP =
2272
+ cxxMethodDecl (hasName (" f" ), hasParent (cxxRecordDecl (hasName (" B" ))));
2273
+ auto DFP =
2274
+ cxxMethodDecl (hasName (" f" ), hasParent (cxxRecordDecl (hasName (" D" ))));
2275
+ auto BFDefP = cxxMethodDecl (
2276
+ hasName (" f" ), hasParent (cxxRecordDecl (hasName (" B" ))), isDefinition ());
2277
+ auto DFDefP = cxxMethodDecl (
2278
+ hasName (" f" ), hasParent (cxxRecordDecl (hasName (" D" ))), isDefinition ());
2279
+ auto FDefAllP = cxxMethodDecl (hasName (" f" ), isDefinition ());
2280
+
2281
+ {
2282
+ Decl *FromTU = getTuDecl (CodeWithDef, Lang_CXX, " input0.cc" );
2283
+ auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match (FromTU, DFP);
2284
+ Import (FromD, Lang_CXX);
2285
+ }
2286
+ {
2287
+ Decl *FromTU = getTuDecl (CodeWithoutDef, Lang_CXX, " input1.cc" );
2288
+ auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match (FromTU, BFP);
2289
+ Import (FromB, Lang_CXX);
2290
+ }
2291
+
2292
+ auto *ToTU = ToAST->getASTContext ().getTranslationUnitDecl ();
2293
+
2294
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, BFP), 1u );
2295
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, DFP), 1u );
2296
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, BFDefP), 1u );
2297
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, DFDefP), 1u );
2298
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, FDefAllP), 2u );
2299
+ }
2300
+
2301
+ TEST_P (ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2302
+ auto Code =
2303
+ R"(
2304
+ struct B { virtual void f(); };
2305
+ struct D:B { void f(); };
2306
+ void B::f(){};
2307
+ )" ;
2308
+
2309
+ auto BFP =
2310
+ cxxMethodDecl (hasName (" f" ), hasParent (cxxRecordDecl (hasName (" B" ))));
2311
+ auto BFDefP = cxxMethodDecl (
2312
+ hasName (" f" ), hasParent (cxxRecordDecl (hasName (" B" ))), isDefinition ());
2313
+ auto DFP = cxxMethodDecl (hasName (" f" ), hasParent (cxxRecordDecl (hasName (" D" ))),
2314
+ unless (isDefinition ()));
2315
+
2316
+ Decl *FromTU0 = getTuDecl (Code, Lang_CXX);
2317
+ auto *D = FirstDeclMatcher<CXXMethodDecl>().match (FromTU0, DFP);
2318
+ Import (D, Lang_CXX);
2319
+
2320
+ Decl *FromTU1 = getTuDecl (Code, Lang_CXX, " input1.cc" );
2321
+ auto *B = FirstDeclMatcher<CXXMethodDecl>().match (FromTU1, BFP);
2322
+ Import (B, Lang_CXX);
2323
+
2324
+ auto *ToTU = ToAST->getASTContext ().getTranslationUnitDecl ();
2325
+
2326
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, BFP), 1u );
2327
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, BFDefP), 0u );
2328
+
2329
+ auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match (
2330
+ ToTU, cxxRecordDecl (hasName (" B" )));
2331
+ auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match (ToTU, BFP);
2332
+ auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match (
2333
+ ToTU, cxxMethodDecl (hasName (" f" ), isDefinition ()));
2334
+
2335
+ // The definition should be out-of-class.
2336
+ EXPECT_NE (ToBFInClass, ToBFOutOfClass);
2337
+ EXPECT_NE (ToBFInClass->getLexicalDeclContext (),
2338
+ ToBFOutOfClass->getLexicalDeclContext ());
2339
+ EXPECT_EQ (ToBFOutOfClass->getDeclContext (), ToB);
2340
+ EXPECT_EQ (ToBFOutOfClass->getLexicalDeclContext (), ToTU);
2341
+
2342
+ // Check that the redecl chain is intact.
2343
+ EXPECT_EQ (ToBFOutOfClass->getPreviousDecl (), ToBFInClass);
2344
+ }
2345
+
2346
+ TEST_P (ImportFunctions,
2347
+ ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2348
+ auto CodeTU0 =
2349
+ R"(
2350
+ struct B { virtual void f(); };
2351
+ struct D:B { void f(); };
2352
+ )" ;
2353
+ auto CodeTU1 =
2354
+ R"(
2355
+ struct B { virtual void f(); };
2356
+ struct D:B { void f(); };
2357
+ void B::f(){}
2358
+ void D::f(){}
2359
+ void foo(B &b, D &d) { b.f(); d.f(); }
2360
+ )" ;
2361
+
2362
+ auto BFP =
2363
+ cxxMethodDecl (hasName (" f" ), hasParent (cxxRecordDecl (hasName (" B" ))));
2364
+ auto BFDefP = cxxMethodDecl (
2365
+ hasName (" f" ), hasParent (cxxRecordDecl (hasName (" B" ))), isDefinition ());
2366
+ auto DFP =
2367
+ cxxMethodDecl (hasName (" f" ), hasParent (cxxRecordDecl (hasName (" D" ))));
2368
+ auto DFDefP = cxxMethodDecl (
2369
+ hasName (" f" ), hasParent (cxxRecordDecl (hasName (" D" ))), isDefinition ());
2370
+ auto FooDef = functionDecl (hasName (" foo" ));
2371
+
2372
+ {
2373
+ Decl *FromTU0 = getTuDecl (CodeTU0, Lang_CXX, " input0.cc" );
2374
+ auto *D = FirstDeclMatcher<CXXMethodDecl>().match (FromTU0, DFP);
2375
+ Import (D, Lang_CXX);
2376
+ }
2377
+
2378
+ {
2379
+ Decl *FromTU1 = getTuDecl (CodeTU1, Lang_CXX, " input1.cc" );
2380
+ auto *Foo = FirstDeclMatcher<FunctionDecl>().match (FromTU1, FooDef);
2381
+ Import (Foo, Lang_CXX);
2382
+ }
2383
+
2384
+ auto *ToTU = ToAST->getASTContext ().getTranslationUnitDecl ();
2385
+
2386
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, BFP), 1u );
2387
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, DFP), 1u );
2388
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, BFDefP), 0u );
2389
+ EXPECT_EQ (DeclCounter<FunctionDecl>().match (ToTU, DFDefP), 0u );
2390
+
2391
+ auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match (
2392
+ ToTU, cxxRecordDecl (hasName (" B" )));
2393
+ auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match (
2394
+ ToTU, cxxRecordDecl (hasName (" D" )));
2395
+ auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match (ToTU, BFP);
2396
+ auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match (
2397
+ ToTU, cxxMethodDecl (hasName (" f" ), isDefinition ()));
2398
+ auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match (ToTU, DFP);
2399
+ auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match (
2400
+ ToTU, cxxMethodDecl (hasName (" f" ), isDefinition ()));
2401
+
2402
+ // The definition should be out-of-class.
2403
+ EXPECT_NE (ToBFInClass, ToBFOutOfClass);
2404
+ EXPECT_NE (ToBFInClass->getLexicalDeclContext (),
2405
+ ToBFOutOfClass->getLexicalDeclContext ());
2406
+ EXPECT_EQ (ToBFOutOfClass->getDeclContext (), ToB);
2407
+ EXPECT_EQ (ToBFOutOfClass->getLexicalDeclContext (), ToTU);
2408
+
2409
+ EXPECT_NE (ToDFInClass, ToDFOutOfClass);
2410
+ EXPECT_NE (ToDFInClass->getLexicalDeclContext (),
2411
+ ToDFOutOfClass->getLexicalDeclContext ());
2412
+ EXPECT_EQ (ToDFOutOfClass->getDeclContext (), ToD);
2413
+ EXPECT_EQ (ToDFOutOfClass->getLexicalDeclContext (), ToTU);
2414
+
2415
+ // Check that the redecl chain is intact.
2416
+ EXPECT_EQ (ToBFOutOfClass->getPreviousDecl (), ToBFInClass);
2417
+ EXPECT_EQ (ToDFOutOfClass->getPreviousDecl (), ToDFInClass);
2418
+ }
2419
+
2235
2420
struct ImportFriendFunctions : ImportFunctions {};
2236
2421
2237
2422
TEST_P (ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
0 commit comments