clang: lib/AST/ODRDiagsEmitter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

15

16using namespace clang;

17

23

29

36

42

44

46 return M->getFullModuleName();

47

48

49 return {};

50}

51

52template

55 StringRef FirstModule,

56 StringRef SecondModule,

57 const MethodT *FirstMethod,

58 const MethodT *SecondMethod) {

59 enum DiagMethodType {

60 DiagMethod,

61 DiagConstructor,

62 DiagDestructor,

63 };

64 auto GetDiagMethodType = [](const NamedDecl *D) {

66 return DiagConstructor;

68 return DiagDestructor;

69 return DiagMethod;

70 };

71

72 enum ODRMethodParametersDifference {

73 NumberParameters,

74 ParameterType,

75 ParameterName,

76 };

77 auto DiagError = [&Diags, &GetDiagMethodType, FirstContainer, FirstModule,

78 FirstMethod](ODRMethodParametersDifference DiffType) {

80 DiagMethodType FirstMethodType = GetDiagMethodType(FirstMethod);

81 return Diags.Report(FirstMethod->getLocation(),

82 diag::err_module_odr_violation_method_params)

83 << FirstContainer << FirstModule.empty() << FirstModule

84 << FirstMethod->getSourceRange() << DiffType << FirstMethodType

85 << FirstName;

86 };

87 auto DiagNote = [&Diags, &GetDiagMethodType, SecondModule,

88 SecondMethod](ODRMethodParametersDifference DiffType) {

90 DiagMethodType SecondMethodType = GetDiagMethodType(SecondMethod);

91 return Diags.Report(SecondMethod->getLocation(),

92 diag::note_module_odr_violation_method_params)

93 << SecondModule.empty() << SecondModule

94 << SecondMethod->getSourceRange() << DiffType << SecondMethodType

95 << SecondName;

96 };

97

98 const unsigned FirstNumParameters = FirstMethod->param_size();

99 const unsigned SecondNumParameters = SecondMethod->param_size();

100 if (FirstNumParameters != SecondNumParameters) {

101 DiagError(NumberParameters) << FirstNumParameters;

102 DiagNote(NumberParameters) << SecondNumParameters;

103 return true;

104 }

105

106 for (unsigned I = 0; I < FirstNumParameters; ++I) {

107 const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I);

108 const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I);

109

112 if (FirstParamType != SecondParamType &&

114 if (const DecayedType *ParamDecayedType =

116 DiagError(ParameterType) << (I + 1) << FirstParamType << true

117 << ParamDecayedType->getOriginalType();

118 } else {

119 DiagError(ParameterType) << (I + 1) << FirstParamType << false;

120 }

121

122 if (const DecayedType *ParamDecayedType =

124 DiagNote(ParameterType) << (I + 1) << SecondParamType << true

125 << ParamDecayedType->getOriginalType();

126 } else {

127 DiagNote(ParameterType) << (I + 1) << SecondParamType << false;

128 }

129 return true;

130 }

131

134 if (FirstParamName != SecondParamName) {

135 DiagError(ParameterName) << (I + 1) << FirstParamName;

136 DiagNote(ParameterName) << (I + 1) << SecondParamName;

137 return true;

138 }

139 }

140

141 return false;

142}

143

144bool ODRDiagsEmitter::diagnoseSubMismatchField(

145 const NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule,

147 enum ODRFieldDifference {

148 FieldName,

149 FieldTypeName,

150 FieldSingleBitField,

151 FieldDifferentWidthBitField,

152 FieldSingleMutable,

153 FieldSingleInitializer,

154 FieldDifferentInitializers,

155 };

156

157 auto DiagError = [FirstRecord, FirstField, FirstModule,

158 this](ODRFieldDifference DiffType) {

159 return Diag(FirstField->getLocation(), diag::err_module_odr_violation_field)

160 << FirstRecord << FirstModule.empty() << FirstModule

162 };

163 auto DiagNote = [SecondField, SecondModule,

164 this](ODRFieldDifference DiffType) {

166 diag::note_module_odr_violation_field)

167 << SecondModule.empty() << SecondModule << SecondField->getSourceRange() << DiffType;

168 };

169

170 IdentifierInfo *FirstII = FirstField->getIdentifier();

171 IdentifierInfo *SecondII = SecondField->getIdentifier();

173 DiagError(FieldName) << FirstII;

174 DiagNote(FieldName) << SecondII;

175 return true;

176 }

177

178 QualType FirstType = FirstField->getType();

179 QualType SecondType = SecondField->getType();

181 DiagError(FieldTypeName) << FirstII << FirstType;

182 DiagNote(FieldTypeName) << SecondII << SecondType;

183 return true;

184 }

185

186 assert(Context.hasSameType(FirstField->getType(), SecondField->getType()));

187 (void)Context;

188

189 const bool IsFirstBitField = FirstField->isBitField();

190 const bool IsSecondBitField = SecondField->isBitField();

191 if (IsFirstBitField != IsSecondBitField) {

192 DiagError(FieldSingleBitField) << FirstII << IsFirstBitField;

193 DiagNote(FieldSingleBitField) << SecondII << IsSecondBitField;

194 return true;

195 }

196

197 if (IsFirstBitField && IsSecondBitField) {

200 if (FirstBitWidthHash != SecondBitWidthHash) {

201 DiagError(FieldDifferentWidthBitField)

203 DiagNote(FieldDifferentWidthBitField)

205 return true;

206 }

207 }

208

209 if (!LangOpts.CPlusPlus)

210 return false;

211

212 const bool IsFirstMutable = FirstField->isMutable();

213 const bool IsSecondMutable = SecondField->isMutable();

214 if (IsFirstMutable != IsSecondMutable) {

215 DiagError(FieldSingleMutable) << FirstII << IsFirstMutable;

216 DiagNote(FieldSingleMutable) << SecondII << IsSecondMutable;

217 return true;

218 }

219

222 if ((!FirstInitializer && SecondInitializer) ||

223 (FirstInitializer && !SecondInitializer)) {

224 DiagError(FieldSingleInitializer)

225 << FirstII << (FirstInitializer != nullptr);

226 DiagNote(FieldSingleInitializer)

227 << SecondII << (SecondInitializer != nullptr);

228 return true;

229 }

230

231 if (FirstInitializer && SecondInitializer) {

232 unsigned FirstInitHash = computeODRHash(FirstInitializer);

233 unsigned SecondInitHash = computeODRHash(SecondInitializer);

234 if (FirstInitHash != SecondInitHash) {

235 DiagError(FieldDifferentInitializers)

237 DiagNote(FieldDifferentInitializers)

239 return true;

240 }

241 }

242

243 return false;

244}

245

246bool ODRDiagsEmitter::diagnoseSubMismatchTypedef(

247 const NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule,

249 bool IsTypeAlias) const {

250 enum ODRTypedefDifference {

251 TypedefName,

252 TypedefType,

253 };

254

255 auto DiagError = [FirstRecord, FirstTD, FirstModule,

256 this](ODRTypedefDifference DiffType) {

257 return Diag(FirstTD->getLocation(), diag::err_module_odr_violation_typedef)

258 << FirstRecord << FirstModule.empty() << FirstModule

260 };

261 auto DiagNote = [SecondTD, SecondModule,

262 this](ODRTypedefDifference DiffType) {

264 diag::note_module_odr_violation_typedef)

265 << SecondModule << SecondTD->getSourceRange() << DiffType;

266 };

267

268 DeclarationName FirstName = FirstTD->getDeclName();

269 DeclarationName SecondName = SecondTD->getDeclName();

270 if (FirstName != SecondName) {

271 DiagError(TypedefName) << IsTypeAlias << FirstName;

272 DiagNote(TypedefName) << IsTypeAlias << SecondName;

273 return true;

274 }

275

279 DiagError(TypedefType) << IsTypeAlias << FirstName << FirstType;

280 DiagNote(TypedefType) << IsTypeAlias << SecondName << SecondType;

281 return true;

282 }

283 return false;

284}

285

286bool ODRDiagsEmitter::diagnoseSubMismatchVar(const NamedDecl *FirstRecord,

287 StringRef FirstModule,

288 StringRef SecondModule,

290 const VarDecl *SecondVD) const {

291 enum ODRVarDifference {

292 VarName,

293 VarType,

294 VarSingleInitializer,

295 VarDifferentInitializer,

296 VarConstexpr,

297 };

298

299 auto DiagError = [FirstRecord, FirstVD, FirstModule,

300 this](ODRVarDifference DiffType) {

301 return Diag(FirstVD->getLocation(), diag::err_module_odr_violation_variable)

302 << FirstRecord << FirstModule.empty() << FirstModule

304 };

305 auto DiagNote = [SecondVD, SecondModule, this](ODRVarDifference DiffType) {

307 diag::note_module_odr_violation_variable)

308 << SecondModule << SecondVD->getSourceRange() << DiffType;

309 };

310

311 DeclarationName FirstName = FirstVD->getDeclName();

312 DeclarationName SecondName = SecondVD->getDeclName();

313 if (FirstName != SecondName) {

314 DiagError(VarName) << FirstName;

315 DiagNote(VarName) << SecondName;

316 return true;

317 }

318

319 QualType FirstType = FirstVD->getType();

320 QualType SecondType = SecondVD->getType();

322 DiagError(VarType) << FirstName << FirstType;

323 DiagNote(VarType) << SecondName << SecondType;

324 return true;

325 }

326

327 if (!LangOpts.CPlusPlus)

328 return false;

329

330 const Expr *FirstInit = FirstVD->getInit();

331 const Expr *SecondInit = SecondVD->getInit();

332 if ((FirstInit == nullptr) != (SecondInit == nullptr)) {

333 DiagError(VarSingleInitializer)

334 << FirstName << (FirstInit == nullptr)

335 << (FirstInit ? FirstInit->getSourceRange() : SourceRange());

336 DiagNote(VarSingleInitializer)

337 << SecondName << (SecondInit == nullptr)

338 << (SecondInit ? SecondInit->getSourceRange() : SourceRange());

339 return true;

340 }

341

342 if (FirstInit && SecondInit &&

344 DiagError(VarDifferentInitializer)

345 << FirstName << FirstInit->getSourceRange();

346 DiagNote(VarDifferentInitializer)

347 << SecondName << SecondInit->getSourceRange();

348 return true;

349 }

350

351 const bool FirstIsConstexpr = FirstVD->isConstexpr();

352 const bool SecondIsConstexpr = SecondVD->isConstexpr();

353 if (FirstIsConstexpr != SecondIsConstexpr) {

354 DiagError(VarConstexpr) << FirstName << FirstIsConstexpr;

355 DiagNote(VarConstexpr) << SecondName << SecondIsConstexpr;

356 return true;

357 }

358 return false;

359}

360

361bool ODRDiagsEmitter::diagnoseSubMismatchProtocols(

365 const ObjCContainerDecl *SecondContainer, StringRef SecondModule) const {

366

367 enum ODRReferencedProtocolDifference {

368 NumProtocols,

369 ProtocolType,

370 };

371 auto DiagRefProtocolError = [FirstContainer, FirstModule,

372 this](SourceLocation Loc, SourceRange Range,

373 ODRReferencedProtocolDifference DiffType) {

374 return Diag(Loc, diag::err_module_odr_violation_referenced_protocols)

375 << FirstContainer << FirstModule.empty() << FirstModule << Range

376 << DiffType;

377 };

378 auto DiagRefProtocolNote = [SecondModule,

379 this](SourceLocation Loc, SourceRange Range,

380 ODRReferencedProtocolDifference DiffType) {

381 return Diag(Loc, diag::note_module_odr_violation_referenced_protocols)

382 << SecondModule.empty() << SecondModule << Range << DiffType;

383 };

384 auto GetProtoListSourceRange = [](const ObjCProtocolList &PL) {

385 if (PL.empty())

386 return SourceRange();

387 return SourceRange(*PL.loc_begin(), *std::prev(PL.loc_end()));

388 };

389

390 if (FirstProtocols.size() != SecondProtocols.size()) {

391 DiagRefProtocolError(FirstContainer->getLocation(),

392 GetProtoListSourceRange(FirstProtocols), NumProtocols)

393 << FirstProtocols.size();

394 DiagRefProtocolNote(SecondContainer->getLocation(),

395 GetProtoListSourceRange(SecondProtocols), NumProtocols)

396 << SecondProtocols.size();

397 return true;

398 }

399

400 for (unsigned I = 0, E = FirstProtocols.size(); I != E; ++I) {

401 const ObjCProtocolDecl *FirstProtocol = FirstProtocols[I];

402 const ObjCProtocolDecl *SecondProtocol = SecondProtocols[I];

403 DeclarationName FirstProtocolName = FirstProtocol->getDeclName();

404 DeclarationName SecondProtocolName = SecondProtocol->getDeclName();

405 if (FirstProtocolName != SecondProtocolName) {

406 SourceLocation FirstLoc = *(FirstProtocols.loc_begin() + I);

407 SourceLocation SecondLoc = *(SecondProtocols.loc_begin() + I);

408 SourceRange EmptyRange;

409 DiagRefProtocolError(FirstLoc, EmptyRange, ProtocolType)

410 << (I + 1) << FirstProtocolName;

411 DiagRefProtocolNote(SecondLoc, EmptyRange, ProtocolType)

412 << (I + 1) << SecondProtocolName;

413 return true;

414 }

415 }

416

417 return false;

418}

419

420bool ODRDiagsEmitter::diagnoseSubMismatchObjCMethod(

421 const NamedDecl *FirstObjCContainer, StringRef FirstModule,

422 StringRef SecondModule, const ObjCMethodDecl *FirstMethod,

424 enum ODRMethodDifference {

425 ReturnType,

426 InstanceOrClass,

427 ControlLevel,

428 DesignatedInitializer,

429 Directness,

430 Name,

431 };

432

433 auto DiagError = [FirstObjCContainer, FirstModule, FirstMethod,

434 this](ODRMethodDifference DiffType) {

436 diag::err_module_odr_violation_objc_method)

437 << FirstObjCContainer << FirstModule.empty() << FirstModule

439 };

440 auto DiagNote = [SecondModule, SecondMethod,

441 this](ODRMethodDifference DiffType) {

442 return Diag(SecondMethod->getLocation(),

443 diag::note_module_odr_violation_objc_method)

444 << SecondModule.empty() << SecondModule

445 << SecondMethod->getSourceRange() << DiffType;

446 };

447

450 DiagError(ReturnType) << FirstMethod << FirstMethod->getReturnType();

451 DiagNote(ReturnType) << SecondMethod << SecondMethod->getReturnType();

452 return true;

453 }

454

455 if (FirstMethod->isInstanceMethod() != SecondMethod->isInstanceMethod()) {

456 DiagError(InstanceOrClass)

458 DiagNote(InstanceOrClass)

459 << SecondMethod << SecondMethod->isInstanceMethod();

460 return true;

461 }

463 SecondMethod->getImplementationControl()) {

465 DiagNote(ControlLevel) << SecondMethod->getImplementationControl();

466 return true;

467 }

469 SecondMethod->isThisDeclarationADesignatedInitializer()) {

470 DiagError(DesignatedInitializer)

471 << FirstMethod

473 DiagNote(DesignatedInitializer)

474 << SecondMethod

475 << SecondMethod->isThisDeclarationADesignatedInitializer();

476 return true;

477 }

478 if (FirstMethod->isDirectMethod() != SecondMethod->isDirectMethod()) {

479 DiagError(Directness) << FirstMethod << FirstMethod->isDirectMethod();

480 DiagNote(Directness) << SecondMethod << SecondMethod->isDirectMethod();

481 return true;

482 }

484 FirstModule, SecondModule,

485 FirstMethod, SecondMethod))

486 return true;

487

488

489

490

491 DeclarationName FirstName = FirstMethod->getDeclName();

492 DeclarationName SecondName = SecondMethod->getDeclName();

493 if (FirstName != SecondName) {

494 DiagError(Name) << FirstName;

495 DiagNote(Name) << SecondName;

496 return true;

497 }

498

499 return false;

500}

501

502bool ODRDiagsEmitter::diagnoseSubMismatchObjCProperty(

503 const NamedDecl *FirstObjCContainer, StringRef FirstModule,

506 enum ODRPropertyDifference {

507 Name,

509 ControlLevel,

510 Attribute,

511 };

512

513 auto DiagError = [FirstObjCContainer, FirstModule, FirstProp,

514 this](SourceLocation Loc, ODRPropertyDifference DiffType) {

515 return Diag(Loc, diag::err_module_odr_violation_objc_property)

516 << FirstObjCContainer << FirstModule.empty() << FirstModule

518 };

519 auto DiagNote = [SecondModule, SecondProp,

520 this](SourceLocation Loc, ODRPropertyDifference DiffType) {

521 return Diag(Loc, diag::note_module_odr_violation_objc_property)

522 << SecondModule.empty() << SecondModule

523 << SecondProp->getSourceRange() << DiffType;

524 };

525

526 IdentifierInfo *FirstII = FirstProp->getIdentifier();

527 IdentifierInfo *SecondII = SecondProp->getIdentifier();

529 DiagError(FirstProp->getLocation(), Name) << FirstII;

530 DiagNote(SecondProp->getLocation(), Name) << SecondII;

531 return true;

532 }

536 << FirstII << FirstProp->getType();

537 DiagNote(SecondProp->getLocation(), Type)

538 << SecondII << SecondProp->getType();

539 return true;

540 }

542 SecondProp->getPropertyImplementation()) {

543 DiagError(FirstProp->getLocation(), ControlLevel)

545 DiagNote(SecondProp->getLocation(), ControlLevel)

546 << SecondProp->getPropertyImplementation();

547 return true;

548 }

549

550

552 unsigned SecondAttrs = (unsigned)SecondProp->getPropertyAttributes();

553 if (FirstAttrs != SecondAttrs) {

555 unsigned CheckedAttr = (1 << I);

556 if ((FirstAttrs & CheckedAttr) == (SecondAttrs & CheckedAttr))

557 continue;

558

559 bool IsFirstWritten =

561 bool IsSecondWritten =

562 (unsigned)SecondProp->getPropertyAttributesAsWritten() & CheckedAttr;

563 DiagError(IsFirstWritten ? FirstProp->getLParenLoc()

565 Attribute)

566 << FirstII << (I + 1) << IsFirstWritten;

567 DiagNote(IsSecondWritten ? SecondProp->getLParenLoc()

568 : SecondProp->getLocation(),

569 Attribute)

570 << SecondII << (I + 1);

571 return true;

572 }

573 }

574

575 return false;

576}

577

578ODRDiagsEmitter::DiffResult

579ODRDiagsEmitter::FindTypeDiffs(DeclHashes &FirstHashes,

580 DeclHashes &SecondHashes) {

581 auto DifferenceSelector = [](const Decl *D) {

582 assert(D && "valid Decl required");

583 switch (D->getKind()) {

584 default:

585 return Other;

586 case Decl::AccessSpec:

587 switch (D->getAccess()) {

589 return PublicSpecifer;

591 return PrivateSpecifer;

593 return ProtectedSpecifer;

595 break;

596 }

597 llvm_unreachable("Invalid access specifier");

598 case Decl::StaticAssert:

599 return StaticAssert;

600 case Decl::Field:

601 return Field;

602 case Decl::CXXMethod:

603 case Decl::CXXConstructor:

604 case Decl::CXXDestructor:

605 return CXXMethod;

606 case Decl::TypeAlias:

607 return TypeAlias;

608 case Decl::Typedef:

609 return TypeDef;

610 case Decl::Var:

611 return Var;

612 case Decl::Friend:

613 return Friend;

614 case Decl::FunctionTemplate:

615 return FunctionTemplate;

616 case Decl::ObjCMethod:

617 return ObjCMethod;

618 case Decl::ObjCIvar:

619 return ObjCIvar;

620 case Decl::ObjCProperty:

621 return ObjCProperty;

622 }

623 };

624

625 DiffResult DR;

626 auto FirstIt = FirstHashes.begin();

627 auto SecondIt = SecondHashes.begin();

628 while (FirstIt != FirstHashes.end() || SecondIt != SecondHashes.end()) {

629 if (FirstIt != FirstHashes.end() && SecondIt != SecondHashes.end() &&

630 FirstIt->second == SecondIt->second) {

631 ++FirstIt;

632 ++SecondIt;

633 continue;

634 }

635

636 DR.FirstDecl = FirstIt == FirstHashes.end() ? nullptr : FirstIt->first;

637 DR.SecondDecl = SecondIt == SecondHashes.end() ? nullptr : SecondIt->first;

638

639 DR.FirstDiffType =

640 DR.FirstDecl ? DifferenceSelector(DR.FirstDecl) : EndOfClass;

641 DR.SecondDiffType =

642 DR.SecondDecl ? DifferenceSelector(DR.SecondDecl) : EndOfClass;

643 return DR;

644 }

645 return DR;

646}

647

648void ODRDiagsEmitter::diagnoseSubMismatchUnexpected(

649 DiffResult &DR, const NamedDecl *FirstRecord, StringRef FirstModule,

650 const NamedDecl *SecondRecord, StringRef SecondModule) const {

652 diag::err_module_odr_violation_different_definitions)

653 << FirstRecord << FirstModule.empty() << FirstModule;

654

655 if (DR.FirstDecl) {

656 Diag(DR.FirstDecl->getLocation(), diag::note_first_module_difference)

658 }

659

661 diag::note_module_odr_violation_different_definitions)

662 << SecondModule;

663

664 if (DR.SecondDecl) {

665 Diag(DR.SecondDecl->getLocation(), diag::note_second_module_difference)

666 << DR.SecondDecl->getSourceRange();

667 }

668}

669

670void ODRDiagsEmitter::diagnoseSubMismatchDifferentDeclKinds(

671 DiffResult &DR, const NamedDecl *FirstRecord, StringRef FirstModule,

672 const NamedDecl *SecondRecord, StringRef SecondModule) const {

673 auto GetMismatchedDeclLoc = [](const NamedDecl *Container,

674 ODRMismatchDecl DiffType, const Decl *D) {

675 SourceLocation Loc;

676 SourceRange Range;

677 if (DiffType == EndOfClass) {

678 if (auto *Tag = dyn_cast(Container))

679 Loc = Tag->getBraceRange().getEnd();

680 else if (auto *IF = dyn_cast(Container))

681 Loc = IF->getAtEndRange().getBegin();

682 else

684 } else {

685 Loc = D->getLocation();

686 Range = D->getSourceRange();

687 }

688 return std::make_pair(Loc, Range);

689 };

690

691 auto FirstDiagInfo =

692 GetMismatchedDeclLoc(FirstRecord, DR.FirstDiffType, DR.FirstDecl);

693 Diag(FirstDiagInfo.first, diag::err_module_odr_violation_mismatch_decl)

694 << FirstRecord << FirstModule.empty() << FirstModule

695 << FirstDiagInfo.second << DR.FirstDiffType;

696

697 auto SecondDiagInfo =

698 GetMismatchedDeclLoc(SecondRecord, DR.SecondDiffType, DR.SecondDecl);

699 Diag(SecondDiagInfo.first, diag::note_module_odr_violation_mismatch_decl)

700 << SecondModule.empty() << SecondModule << SecondDiagInfo.second

701 << DR.SecondDiffType;

702}

703

706 const struct CXXRecordDecl::DefinitionData *SecondDD) const {

707

708

709 if (FirstRecord == SecondRecord)

710 return false;

711

714

715 const struct CXXRecordDecl::DefinitionData *FirstDD =

716 FirstRecord->DefinitionData;

717 assert(FirstDD && SecondDD && "Definitions without DefinitionData");

718

719

720 if (FirstDD != SecondDD) {

721

722 enum ODRDefinitionDataDifference {

723 NumBases,

724 NumVBases,

725 BaseType,

726 BaseVirtual,

727 BaseAccess,

728 };

729 auto DiagBaseError = [FirstRecord, &FirstModule,

731 ODRDefinitionDataDifference DiffType) {

732 return Diag(Loc, diag::err_module_odr_violation_definition_data)

733 << FirstRecord << FirstModule.empty() << FirstModule << Range

734 << DiffType;

735 };

736 auto DiagBaseNote = [&SecondModule,

738 ODRDefinitionDataDifference DiffType) {

739 return Diag(Loc, diag::note_module_odr_violation_definition_data)

740 << SecondModule << Range << DiffType;

741 };

742 auto GetSourceRange = [](const struct CXXRecordDecl::DefinitionData *DD) {

743 unsigned NumBases = DD->NumBases;

744 if (NumBases == 0)

747 return SourceRange(bases[0].getBeginLoc(),

748 bases[NumBases - 1].getEndLoc());

749 };

750

751 unsigned FirstNumBases = FirstDD->NumBases;

752 unsigned FirstNumVBases = FirstDD->NumVBases;

753 unsigned SecondNumBases = SecondDD->NumBases;

754 unsigned SecondNumVBases = SecondDD->NumVBases;

755 if (FirstNumBases != SecondNumBases) {

756 DiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),

757 NumBases)

758 << FirstNumBases;

759 DiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),

760 NumBases)

761 << SecondNumBases;

762 return true;

763 }

764

765 if (FirstNumVBases != SecondNumVBases) {

766 DiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD),

767 NumVBases)

768 << FirstNumVBases;

769 DiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD),

770 NumVBases)

771 << SecondNumVBases;

772 return true;

773 }

774

777 for (unsigned I = 0; I < FirstNumBases; ++I) {

783 BaseType)

784 << (I + 1) << FirstBase.getType();

786 BaseType)

787 << (I + 1) << SecondBase.getType();

788 return true;

789 }

790

793 BaseVirtual)

796 BaseVirtual)

797 << (I + 1) << SecondBase.isVirtual() << SecondBase.getType();

798 return true;

799 }

800

804 BaseAccess)

805 << (I + 1) << FirstBase.getType()

808 BaseAccess)

809 << (I + 1) << SecondBase.getType()

811 return true;

812 }

813 }

814 }

815

820

821 assert(!FirstTemplate == !SecondTemplate &&

822 "Both pointers should be null or non-null");

823

824 if (FirstTemplate && SecondTemplate) {

829 assert(FirstTemplateParams.size() == SecondTemplateParams.size() &&

830 "Number of template parameters should be equal.");

831 for (auto Pair : llvm::zip(FirstTemplateParams, SecondTemplateParams)) {

832 const NamedDecl *FirstDecl = std::get<0>(Pair);

833 const NamedDecl *SecondDecl = std::get<1>(Pair);

835 continue;

836

837 assert(FirstDecl->getKind() == SecondDecl->getKind() &&

838 "Parameter Decl's should be the same kind.");

839

840 enum ODRTemplateDifference {

841 ParamEmptyName,

842 ParamName,

843 ParamSingleDefaultArgument,

844 ParamDifferentDefaultArgument,

845 };

846

847 auto hasDefaultArg = [](const NamedDecl *D) {

848 if (auto *TTP = dyn_cast(D))

849 return TTP->hasDefaultArgument() &&

850 !TTP->defaultArgumentWasInherited();

851 if (auto *NTTP = dyn_cast(D))

852 return NTTP->hasDefaultArgument() &&

853 !NTTP->defaultArgumentWasInherited();

855 return TTP->hasDefaultArgument() && !TTP->defaultArgumentWasInherited();

856 };

857 bool hasFirstArg = hasDefaultArg(FirstDecl);

858 bool hasSecondArg = hasDefaultArg(SecondDecl);

859

860 ODRTemplateDifference ErrDiffType;

861 ODRTemplateDifference NoteDiffType;

862

865

866 if (FirstName != SecondName) {

867 bool FirstNameEmpty =

869 bool SecondNameEmpty =

871 ErrDiffType = FirstNameEmpty ? ParamEmptyName : ParamName;

872 NoteDiffType = SecondNameEmpty ? ParamEmptyName : ParamName;

873 } else if (hasFirstArg == hasSecondArg)

874 ErrDiffType = NoteDiffType = ParamDifferentDefaultArgument;

875 else

876 ErrDiffType = NoteDiffType = ParamSingleDefaultArgument;

877

879 diag::err_module_odr_violation_template_parameter)

880 << FirstRecord << FirstModule.empty() << FirstModule

881 << FirstDecl->getSourceRange() << ErrDiffType << hasFirstArg

882 << FirstName;

884 diag::note_module_odr_violation_template_parameter)

885 << SecondModule << SecondDecl->getSourceRange() << NoteDiffType

886 << hasSecondArg << SecondName;

887 return true;

888 }

889 }

890

891 auto PopulateHashes = [](DeclHashes &Hashes, const RecordDecl *Record,

893 for (const Decl *D : Record->decls()) {

895 continue;

897 }

898 };

899

900 DeclHashes FirstHashes;

901 DeclHashes SecondHashes;

903 PopulateHashes(FirstHashes, FirstRecord, DC);

904 PopulateHashes(SecondHashes, SecondRecord, DC);

905

906 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);

907 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;

908 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;

909 const Decl *FirstDecl = DR.FirstDecl;

910 const Decl *SecondDecl = DR.SecondDecl;

911

912 if (FirstDiffType == Other || SecondDiffType == Other) {

913 diagnoseSubMismatchUnexpected(DR, FirstRecord, FirstModule, SecondRecord,

914 SecondModule);

915 return true;

916 }

917

918 if (FirstDiffType != SecondDiffType) {

919 diagnoseSubMismatchDifferentDeclKinds(DR, FirstRecord, FirstModule,

920 SecondRecord, SecondModule);

921 return true;

922 }

923

924

925

926 enum ODRCXXRecordDifference {

927 StaticAssertCondition,

928 StaticAssertMessage,

929 StaticAssertOnlyMessage,

930 MethodName,

931 MethodDeleted,

932 MethodDefaulted,

933 MethodVirtual,

934 MethodStatic,

935 MethodVolatile,

936 MethodConst,

937 MethodInline,

938 MethodParameterSingleDefaultArgument,

939 MethodParameterDifferentDefaultArgument,

940 MethodNoTemplateArguments,

941 MethodDifferentNumberTemplateArguments,

942 MethodDifferentTemplateArgument,

943 MethodSingleBody,

944 MethodDifferentBody,

945 FriendTypeFunction,

946 FriendType,

947 FriendFunction,

948 FunctionTemplateDifferentNumberParameters,

949 FunctionTemplateParameterDifferentKind,

950 FunctionTemplateParameterName,

951 FunctionTemplateParameterSingleDefaultArgument,

952 FunctionTemplateParameterDifferentDefaultArgument,

953 FunctionTemplateParameterDifferentType,

954 FunctionTemplatePackParameter,

955 };

956 auto DiagError = [FirstRecord, &FirstModule,

958 ODRCXXRecordDifference DiffType) {

959 return Diag(Loc, diag::err_module_odr_violation_record)

960 << FirstRecord << FirstModule.empty() << FirstModule << Range

961 << DiffType;

962 };

964 ODRCXXRecordDifference DiffType) {

965 return Diag(Loc, diag::note_module_odr_violation_record)

966 << SecondModule << Range << DiffType;

967 };

968

969 assert(FirstDiffType == SecondDiffType);

970 switch (FirstDiffType) {

971 case Other:

972 case EndOfClass:

973 case PublicSpecifer:

974 case PrivateSpecifer:

975 case ProtectedSpecifer:

976 case ObjCMethod:

977 case ObjCIvar:

978 case ObjCProperty:

979 llvm_unreachable("Invalid diff type");

980

981 case StaticAssert: {

984

989 if (FirstODRHash != SecondODRHash) {

991 StaticAssertCondition);

993 StaticAssertCondition);

994 return true;

995 }

996

999 assert((FirstMessage || SecondMessage) && "Both messages cannot be empty");

1000 if ((FirstMessage && !SecondMessage) || (!FirstMessage && SecondMessage)) {

1003 if (FirstMessage) {

1006 } else {

1009 }

1010 if (SecondMessage) {

1011 SecondLoc = SecondMessage->getBeginLoc();

1013 } else {

1016 }

1017 DiagError(FirstLoc, FirstRange, StaticAssertOnlyMessage)

1018 << (FirstMessage == nullptr);

1019 DiagNote(SecondLoc, SecondRange, StaticAssertOnlyMessage)

1020 << (SecondMessage == nullptr);

1021 return true;

1022 }

1023

1024 if (FirstMessage && SecondMessage) {

1025 unsigned FirstMessageODRHash = computeODRHash(FirstMessage);

1026 unsigned SecondMessageODRHash = computeODRHash(SecondMessage);

1027 if (FirstMessageODRHash != SecondMessageODRHash) {

1029 StaticAssertMessage);

1031 StaticAssertMessage);

1032 return true;

1033 }

1034 }

1035 break;

1036 }

1037

1038 case Field: {

1039 if (diagnoseSubMismatchField(FirstRecord, FirstModule, SecondModule,

1042 return true;

1043 break;

1044 }

1045

1046 case CXXMethod: {

1047 enum {

1048 DiagMethod,

1049 DiagConstructor,

1050 DiagDestructor,

1051 } FirstMethodType,

1052 SecondMethodType;

1053 auto GetMethodTypeForDiagnostics = [](const CXXMethodDecl *D) {

1055 return DiagConstructor;

1057 return DiagDestructor;

1058 return DiagMethod;

1059 };

1062 FirstMethodType = GetMethodTypeForDiagnostics(FirstMethod);

1063 SecondMethodType = GetMethodTypeForDiagnostics(SecondMethod);

1066 auto DiagMethodError = [&DiagError, FirstMethod, FirstMethodType,

1067 FirstName](ODRCXXRecordDifference DiffType) {

1068 return DiagError(FirstMethod->getLocation(),

1070 << FirstMethodType << FirstName;

1071 };

1072 auto DiagMethodNote = [&DiagNote, SecondMethod, SecondMethodType,

1073 SecondName](ODRCXXRecordDifference DiffType) {

1074 return DiagNote(SecondMethod->getLocation(),

1076 << SecondMethodType << SecondName;

1077 };

1078

1079 if (FirstMethodType != SecondMethodType || FirstName != SecondName) {

1080 DiagMethodError(MethodName);

1081 DiagMethodNote(MethodName);

1082 return true;

1083 }

1084

1087 if (FirstDeleted != SecondDeleted) {

1088 DiagMethodError(MethodDeleted) << FirstDeleted;

1089 DiagMethodNote(MethodDeleted) << SecondDeleted;

1090 return true;

1091 }

1092

1095 if (FirstDefaulted != SecondDefaulted) {

1096 DiagMethodError(MethodDefaulted) << FirstDefaulted;

1097 DiagMethodNote(MethodDefaulted) << SecondDefaulted;

1098 return true;

1099 }

1100

1103 const bool FirstPure = FirstMethod->isPureVirtual();

1104 const bool SecondPure = SecondMethod->isPureVirtual();

1105 if ((FirstVirtual || SecondVirtual) &&

1106 (FirstVirtual != SecondVirtual || FirstPure != SecondPure)) {

1107 DiagMethodError(MethodVirtual) << FirstPure << FirstVirtual;

1108 DiagMethodNote(MethodVirtual) << SecondPure << SecondVirtual;

1109 return true;

1110 }

1111

1112

1113

1114

1117 const bool FirstStatic = FirstStorage == SC_Static;

1118 const bool SecondStatic = SecondStorage == SC_Static;

1119 if (FirstStatic != SecondStatic) {

1120 DiagMethodError(MethodStatic) << FirstStatic;

1121 DiagMethodNote(MethodStatic) << SecondStatic;

1122 return true;

1123 }

1124

1125 const bool FirstVolatile = FirstMethod->isVolatile();

1126 const bool SecondVolatile = SecondMethod->isVolatile();

1127 if (FirstVolatile != SecondVolatile) {

1128 DiagMethodError(MethodVolatile) << FirstVolatile;

1129 DiagMethodNote(MethodVolatile) << SecondVolatile;

1130 return true;

1131 }

1132

1133 const bool FirstConst = FirstMethod->isConst();

1134 const bool SecondConst = SecondMethod->isConst();

1135 if (FirstConst != SecondConst) {

1136 DiagMethodError(MethodConst) << FirstConst;

1137 DiagMethodNote(MethodConst) << SecondConst;

1138 return true;

1139 }

1140

1143 if (FirstInline != SecondInline) {

1144 DiagMethodError(MethodInline) << FirstInline;

1145 DiagMethodNote(MethodInline) << SecondInline;

1146 return true;

1147 }

1148

1150 FirstModule, SecondModule,

1151 FirstMethod, SecondMethod))

1152 return true;

1153

1154 for (unsigned I = 0, N = FirstMethod->param_size(); I < N; ++I) {

1157

1158 const Expr *FirstInit = FirstParam->getInit();

1159 const Expr *SecondInit = SecondParam->getInit();

1160 if ((FirstInit == nullptr) != (SecondInit == nullptr)) {

1161 DiagMethodError(MethodParameterSingleDefaultArgument)

1162 << (I + 1) << (FirstInit == nullptr)

1164 DiagMethodNote(MethodParameterSingleDefaultArgument)

1165 << (I + 1) << (SecondInit == nullptr)

1167 return true;

1168 }

1169

1170 if (FirstInit && SecondInit &&

1172 DiagMethodError(MethodParameterDifferentDefaultArgument)

1174 DiagMethodNote(MethodParameterDifferentDefaultArgument)

1176 return true;

1177 }

1178 }

1179

1184

1185 if ((FirstTemplateArgs && !SecondTemplateArgs) ||

1186 (!FirstTemplateArgs && SecondTemplateArgs)) {

1187 DiagMethodError(MethodNoTemplateArguments)

1188 << (FirstTemplateArgs != nullptr);

1189 DiagMethodNote(MethodNoTemplateArguments)

1190 << (SecondTemplateArgs != nullptr);

1191 return true;

1192 }

1193

1194 if (FirstTemplateArgs && SecondTemplateArgs) {

1195

1200 ExpandedList.push_back(&TA);

1201 continue;

1202 }

1203 llvm::append_range(ExpandedList,

1204 llvm::make_pointer_range(TA.getPackAsArray()));

1205 }

1206 return ExpandedList;

1207 };

1209 ExpandTemplateArgumentList(FirstTemplateArgs);

1211 ExpandTemplateArgumentList(SecondTemplateArgs);

1212

1213 if (FirstExpandedList.size() != SecondExpandedList.size()) {

1214 DiagMethodError(MethodDifferentNumberTemplateArguments)

1215 << (unsigned)FirstExpandedList.size();

1216 DiagMethodNote(MethodDifferentNumberTemplateArguments)

1217 << (unsigned)SecondExpandedList.size();

1218 return true;

1219 }

1220

1221 for (unsigned i = 0, e = FirstExpandedList.size(); i != e; ++i) {

1223 &SecondTA = *SecondExpandedList[i];

1225 continue;

1226

1227 DiagMethodError(MethodDifferentTemplateArgument) << FirstTA << i + 1;

1228 DiagMethodNote(MethodDifferentTemplateArgument) << SecondTA << i + 1;

1229 return true;

1230 }

1231 }

1232

1233

1234 auto ComputeCXXMethodODRHash = [](const CXXMethodDecl *D) {

1238 };

1239

1240

1241

1242

1243 const bool HasFirstBody =

1244 ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash();

1245 const bool HasSecondBody =

1246 ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash();

1247

1248 if (HasFirstBody != HasSecondBody) {

1249 DiagMethodError(MethodSingleBody) << HasFirstBody;

1250 DiagMethodNote(MethodSingleBody) << HasSecondBody;

1251 return true;

1252 }

1253

1254 if (HasFirstBody && HasSecondBody) {

1255 DiagMethodError(MethodDifferentBody);

1256 DiagMethodNote(MethodDifferentBody);

1257 return true;

1258 }

1259

1260 break;

1261 }

1262

1263 case TypeAlias:

1264 case TypeDef: {

1265 if (diagnoseSubMismatchTypedef(FirstRecord, FirstModule, SecondModule,

1268 FirstDiffType == TypeAlias))

1269 return true;

1270 break;

1271 }

1272 case Var: {

1273 if (diagnoseSubMismatchVar(FirstRecord, FirstModule, SecondModule,

1276 return true;

1277 break;

1278 }

1279 case Friend: {

1282

1285

1288

1289 if (FirstND && SecondND) {

1291 FriendFunction)

1292 << FirstND;

1294 FriendFunction)

1295 << SecondND;

1296 return true;

1297 }

1298

1299 if (FirstTSI && SecondTSI) {

1305 FriendType)

1306 << FirstFriendType;

1308 FriendType)

1309 << SecondFriendType;

1310 return true;

1311 }

1312

1314 FriendTypeFunction)

1315 << (FirstTSI == nullptr);

1317 FriendTypeFunction)

1318 << (SecondTSI == nullptr);

1319 return true;

1320 }

1321 case FunctionTemplate: {

1326

1329

1330 auto DiagTemplateError = [&DiagError,

1331 FirstTemplate](ODRCXXRecordDifference DiffType) {

1332 return DiagError(FirstTemplate->getLocation(),

1334 << FirstTemplate;

1335 };

1336 auto DiagTemplateNote = [&DiagNote,

1337 SecondTemplate](ODRCXXRecordDifference DiffType) {

1338 return DiagNote(SecondTemplate->getLocation(),

1340 << SecondTemplate;

1341 };

1342

1343 if (FirstTPL->size() != SecondTPL->size()) {

1344 DiagTemplateError(FunctionTemplateDifferentNumberParameters)

1345 << FirstTPL->size();

1346 DiagTemplateNote(FunctionTemplateDifferentNumberParameters)

1347 << SecondTPL->size();

1348 return true;

1349 }

1350

1351 for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i) {

1354

1355 if (FirstParam->getKind() != SecondParam->getKind()) {

1356 enum {

1357 TemplateTypeParameter,

1358 NonTypeTemplateParameter,

1359 TemplateTemplateParameter,

1360 };

1361 auto GetParamType = [](NamedDecl *D) {

1362 switch (D->getKind()) {

1363 default:

1364 llvm_unreachable("Unexpected template parameter type");

1365 case Decl::TemplateTypeParm:

1366 return TemplateTypeParameter;

1367 case Decl::NonTypeTemplateParm:

1368 return NonTypeTemplateParameter;

1369 case Decl::TemplateTemplateParm:

1370 return TemplateTemplateParameter;

1371 }

1372 };

1373

1374 DiagTemplateError(FunctionTemplateParameterDifferentKind)

1375 << (i + 1) << GetParamType(FirstParam);

1376 DiagTemplateNote(FunctionTemplateParameterDifferentKind)

1377 << (i + 1) << GetParamType(SecondParam);

1378 return true;

1379 }

1380

1381 if (FirstParam->getName() != SecondParam->getName()) {

1382 DiagTemplateError(FunctionTemplateParameterName)

1383 << (i + 1) << (bool)FirstParam->getIdentifier() << FirstParam;

1384 DiagTemplateNote(FunctionTemplateParameterName)

1385 << (i + 1) << (bool)SecondParam->getIdentifier() << SecondParam;

1386 return true;

1387 }

1388

1395 bool HasFirstDefaultArgument =

1398 bool HasSecondDefaultArgument =

1401 if (HasFirstDefaultArgument != HasSecondDefaultArgument) {

1402 DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)

1403 << (i + 1) << HasFirstDefaultArgument;

1404 DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)

1405 << (i + 1) << HasSecondDefaultArgument;

1406 return true;

1407 }

1408

1409 if (HasFirstDefaultArgument && HasSecondDefaultArgument) {

1415 DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)

1416 << (i + 1) << FirstTA;

1417 DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)

1418 << (i + 1) << SecondTA;

1419 return true;

1420 }

1421 }

1422

1424 DiagTemplateError(FunctionTemplatePackParameter)

1426 DiagTemplateNote(FunctionTemplatePackParameter)

1428 return true;

1429 }

1430 }

1431

1438

1441

1442 auto ComputeTemplateParameterListODRHash =

1444 assert(TPL);

1448 };

1449

1450 if (ComputeTemplateParameterListODRHash(FirstTPL) !=

1451 ComputeTemplateParameterListODRHash(SecondTPL)) {

1452 DiagTemplateError(FunctionTemplateParameterDifferentType) << (i + 1);

1453 DiagTemplateNote(FunctionTemplateParameterDifferentType) << (i + 1);

1454 return true;

1455 }

1456

1457 bool HasFirstDefaultArgument =

1460 bool HasSecondDefaultArgument =

1463 if (HasFirstDefaultArgument != HasSecondDefaultArgument) {

1464 DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)

1465 << (i + 1) << HasFirstDefaultArgument;

1466 DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)

1467 << (i + 1) << HasSecondDefaultArgument;

1468 return true;

1469 }

1470

1471 if (HasFirstDefaultArgument && HasSecondDefaultArgument) {

1477 DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)

1478 << (i + 1) << FirstTA;

1479 DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)

1480 << (i + 1) << SecondTA;

1481 return true;

1482 }

1483 }

1484

1486 DiagTemplateError(FunctionTemplatePackParameter)

1488 DiagTemplateNote(FunctionTemplatePackParameter)

1490 return true;

1491 }

1492 }

1493

1500

1504 DiagTemplateError(FunctionTemplateParameterDifferentType) << (i + 1);

1505 DiagTemplateNote(FunctionTemplateParameterDifferentType) << (i + 1);

1506 return true;

1507 }

1508

1509 bool HasFirstDefaultArgument =

1512 bool HasSecondDefaultArgument =

1515 if (HasFirstDefaultArgument != HasSecondDefaultArgument) {

1516 DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument)

1517 << (i + 1) << HasFirstDefaultArgument;

1518 DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument)

1519 << (i + 1) << HasSecondDefaultArgument;

1520 return true;

1521 }

1522

1523 if (HasFirstDefaultArgument && HasSecondDefaultArgument) {

1528

1531 DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument)

1532 << (i + 1) << FirstDefaultArgument;

1533 DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument)

1534 << (i + 1) << SecondDefaultArgument;

1535 return true;

1536 }

1537 }

1538

1540 DiagTemplateError(FunctionTemplatePackParameter)

1542 DiagTemplateNote(FunctionTemplatePackParameter)

1544 return true;

1545 }

1546 }

1547 }

1548 break;

1549 }

1550 }

1551

1553 diag::err_module_odr_violation_mismatch_decl_unknown)

1554 << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType

1557 diag::note_module_odr_violation_mismatch_decl_unknown)

1558 << SecondModule.empty() << SecondModule << FirstDiffType

1560 return true;

1561}

1562

1564 const RecordDecl *SecondRecord) const {

1565 if (FirstRecord == SecondRecord)

1566 return false;

1567

1570

1571 auto PopulateHashes = [](DeclHashes &Hashes, const RecordDecl *Record,

1573 for (const Decl *D : Record->decls()) {

1575 continue;

1577 }

1578 };

1579

1580 DeclHashes FirstHashes;

1581 DeclHashes SecondHashes;

1583 PopulateHashes(FirstHashes, FirstRecord, DC);

1584 PopulateHashes(SecondHashes, SecondRecord, DC);

1585

1586 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);

1587 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;

1588 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;

1589 const Decl *FirstDecl = DR.FirstDecl;

1590 const Decl *SecondDecl = DR.SecondDecl;

1591

1592 if (FirstDiffType == Other || SecondDiffType == Other) {

1593 diagnoseSubMismatchUnexpected(DR, FirstRecord, FirstModule, SecondRecord,

1594 SecondModule);

1595 return true;

1596 }

1597

1598 if (FirstDiffType != SecondDiffType) {

1599 diagnoseSubMismatchDifferentDeclKinds(DR, FirstRecord, FirstModule,

1600 SecondRecord, SecondModule);

1601 return true;

1602 }

1603

1604 assert(FirstDiffType == SecondDiffType);

1605 switch (FirstDiffType) {

1606

1607 case EndOfClass:

1608 case Other:

1609

1610 case PublicSpecifer:

1611 case PrivateSpecifer:

1612 case ProtectedSpecifer:

1613 case StaticAssert:

1614 case CXXMethod:

1615 case TypeAlias:

1616 case Friend:

1617 case FunctionTemplate:

1618

1619 case ObjCMethod:

1620 case ObjCIvar:

1621 case ObjCProperty:

1622 llvm_unreachable("Invalid diff type");

1623

1624 case Field: {

1625 if (diagnoseSubMismatchField(FirstRecord, FirstModule, SecondModule,

1628 return true;

1629 break;

1630 }

1631 case TypeDef: {

1632 if (diagnoseSubMismatchTypedef(FirstRecord, FirstModule, SecondModule,

1635 false))

1636 return true;

1637 break;

1638 }

1639 case Var: {

1640 if (diagnoseSubMismatchVar(FirstRecord, FirstModule, SecondModule,

1643 return true;

1644 break;

1645 }

1646 }

1647

1649 diag::err_module_odr_violation_mismatch_decl_unknown)

1650 << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType

1653 diag::note_module_odr_violation_mismatch_decl_unknown)

1654 << SecondModule.empty() << SecondModule << FirstDiffType

1656 return true;

1657}

1658

1662 if (FirstFunction == SecondFunction)

1663 return false;

1664

1665

1666 enum ODRFunctionDifference {

1667 ReturnType,

1668 ParameterName,

1669 ParameterType,

1670 ParameterSingleDefaultArgument,

1671 ParameterDifferentDefaultArgument,

1672 FunctionBody,

1673 };

1674

1677

1678 auto DiagError = [FirstFunction, &FirstModule,

1680 ODRFunctionDifference DiffType) {

1681 return Diag(Loc, diag::err_module_odr_violation_function)

1682 << FirstFunction << FirstModule.empty() << FirstModule << Range

1683 << DiffType;

1684 };

1686 ODRFunctionDifference DiffType) {

1687 return Diag(Loc, diag::note_module_odr_violation_function)

1688 << SecondModule << Range << DiffType;

1689 };

1690

1699 return true;

1700 }

1701

1703 "Merged functions with different number of parameters");

1704

1705 size_t ParamSize = FirstFunction->param_size();

1706 for (unsigned I = 0; I < ParamSize; ++I) {

1709

1710 assert(Context.hasSameType(FirstParam->getType(), SecondParam->getType()) &&

1711 "Merged function has different parameter types.");

1712

1715 ParameterName)

1718 ParameterName)

1720 return true;

1721 };

1722

1725 if (FirstParamType != SecondParamType &&

1727 if (const DecayedType *ParamDecayedType =

1730 ParameterType)

1731 << (I + 1) << FirstParamType << true

1732 << ParamDecayedType->getOriginalType();

1733 } else {

1735 ParameterType)

1736 << (I + 1) << FirstParamType << false;

1737 }

1738

1739 if (const DecayedType *ParamDecayedType =

1742 ParameterType)

1743 << (I + 1) << SecondParamType << true

1744 << ParamDecayedType->getOriginalType();

1745 } else {

1747 ParameterType)

1748 << (I + 1) << SecondParamType << false;

1749 }

1750 return true;

1751 }

1752

1753

1754 const Expr *FirstInit = FirstParam->getInit();

1755 const Expr *SecondInit = SecondParam->getInit();

1756 if ((FirstInit == nullptr) != (SecondInit == nullptr)) {

1758 ParameterSingleDefaultArgument)

1759 << (I + 1) << (FirstInit == nullptr)

1762 ParameterSingleDefaultArgument)

1763 << (I + 1) << (SecondInit == nullptr)

1765 return true;

1766 }

1767

1768 if (FirstInit && SecondInit &&

1771 ParameterDifferentDefaultArgument)

1774 ParameterDifferentDefaultArgument)

1776 return true;

1777 }

1778

1780 "Undiagnosed parameter difference.");

1781 }

1782

1783

1784

1786 FunctionBody);

1788 FunctionBody);

1789 return true;

1790}

1791

1793 const EnumDecl *SecondEnum) const {

1794 if (FirstEnum == SecondEnum)

1795 return false;

1796

1797

1798 enum ODREnumDifference {

1799 SingleScopedEnum,

1800 EnumTagKeywordMismatch,

1801 SingleSpecifiedType,

1802 DifferentSpecifiedTypes,

1803 DifferentNumberEnumConstants,

1804 EnumConstantName,

1805 EnumConstantSingleInitializer,

1806 EnumConstantDifferentInitializer,

1807 };

1808

1811

1812 auto DiagError = [FirstEnum, &FirstModule, this](const auto *DiagAnchor,

1813 ODREnumDifference DiffType) {

1814 return Diag(DiagAnchor->getLocation(), diag::err_module_odr_violation_enum)

1815 << FirstEnum << FirstModule.empty() << FirstModule

1817 };

1818 auto DiagNote = [&SecondModule, this](const auto *DiagAnchor,

1819 ODREnumDifference DiffType) {

1820 return Diag(DiagAnchor->getLocation(), diag::note_module_odr_violation_enum)

1821 << SecondModule << DiagAnchor->getSourceRange() << DiffType;

1822 };

1823

1825 DiagError(FirstEnum, SingleScopedEnum) << FirstEnum->isScoped();

1826 DiagNote(SecondEnum, SingleScopedEnum) << SecondEnum->isScoped();

1827 return true;

1828 }

1829

1833 DiagError(FirstEnum, EnumTagKeywordMismatch)

1835 DiagNote(SecondEnum, EnumTagKeywordMismatch)

1837 return true;

1838 }

1839 }

1840

1841 QualType FirstUnderlyingType =

1845 QualType SecondUnderlyingType =

1849 if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) {

1850 DiagError(FirstEnum, SingleSpecifiedType) << !FirstUnderlyingType.isNull();

1851 DiagNote(SecondEnum, SingleSpecifiedType) << !SecondUnderlyingType.isNull();

1852 return true;

1853 }

1854

1855 if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()) {

1858 DiagError(FirstEnum, DifferentSpecifiedTypes) << FirstUnderlyingType;

1859 DiagNote(SecondEnum, DifferentSpecifiedTypes) << SecondUnderlyingType;

1860 return true;

1861 }

1862 }

1863

1864

1865 using DeclHashes =

1867 auto PopulateHashes = [FirstEnum](DeclHashes &Hashes, const EnumDecl *Enum) {

1868 for (const Decl *D : Enum->decls()) {

1869

1870

1872 continue;

1875 }

1876 };

1877 DeclHashes FirstHashes;

1878 PopulateHashes(FirstHashes, FirstEnum);

1879 DeclHashes SecondHashes;

1880 PopulateHashes(SecondHashes, SecondEnum);

1881

1882 if (FirstHashes.size() != SecondHashes.size()) {

1883 DiagError(FirstEnum, DifferentNumberEnumConstants)

1884 << (int)FirstHashes.size();

1885 DiagNote(SecondEnum, DifferentNumberEnumConstants)

1886 << (int)SecondHashes.size();

1887 return true;

1888 }

1889

1890 for (unsigned I = 0, N = FirstHashes.size(); I < N; ++I) {

1891 if (FirstHashes[I].second == SecondHashes[I].second)

1892 continue;

1893 const EnumConstantDecl *FirstConstant = FirstHashes[I].first;

1894 const EnumConstantDecl *SecondConstant = SecondHashes[I].first;

1895

1897 DiagError(FirstConstant, EnumConstantName) << I + 1 << FirstConstant;

1898 DiagNote(SecondConstant, EnumConstantName) << I + 1 << SecondConstant;

1899 return true;

1900 }

1901

1904 if (!FirstInit && !SecondInit)

1905 continue;

1906

1907 if (!FirstInit || !SecondInit) {

1908 DiagError(FirstConstant, EnumConstantSingleInitializer)

1909 << I + 1 << FirstConstant << (FirstInit != nullptr);

1910 DiagNote(SecondConstant, EnumConstantSingleInitializer)

1911 << I + 1 << SecondConstant << (SecondInit != nullptr);

1912 return true;

1913 }

1914

1916 DiagError(FirstConstant, EnumConstantDifferentInitializer)

1917 << I + 1 << FirstConstant;

1918 DiagNote(SecondConstant, EnumConstantDifferentInitializer)

1919 << I + 1 << SecondConstant;

1920 return true;

1921 }

1922 }

1923 return false;

1924}

1925

1928 const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const {

1929

1930

1931 if (FirstID == SecondID)

1932 return false;

1933

1936

1937

1938 enum ODRInterfaceDifference {

1939 SuperClassType,

1940 IVarAccess,

1941 };

1942

1943 auto DiagError = [FirstID, &FirstModule,

1945 ODRInterfaceDifference DiffType) {

1946 return Diag(Loc, diag::err_module_odr_violation_objc_interface)

1947 << FirstID << FirstModule.empty() << FirstModule << Range

1948 << DiffType;

1949 };

1951 ODRInterfaceDifference DiffType) {

1952 return Diag(Loc, diag::note_module_odr_violation_objc_interface)

1953 << SecondModule.empty() << SecondModule << Range << DiffType;

1954 };

1955

1956 const struct ObjCInterfaceDecl::DefinitionData *FirstDD = &FirstID->data();

1957 assert(FirstDD && SecondDD && "Definitions without DefinitionData");

1958 if (FirstDD != SecondDD) {

1959

1960 auto GetSuperClassSourceRange = [](const TypeSourceInfo *SuperInfo,

1962 if (!SuperInfo)

1963 return ID->getSourceRange();

1966 };

1967

1971 const TypeSourceInfo *SecondSuperInfo = SecondDD->SuperClassTInfo;

1972 if (SecondSuperInfo)

1973 SecondSuperClass =

1975

1976 if ((FirstSuperClass && SecondSuperClass &&

1978 (FirstSuperClass && !SecondSuperClass) ||

1979 (!FirstSuperClass && SecondSuperClass)) {

1981 if (FirstSuperInfo)

1982 FirstType = FirstSuperInfo->getType();

1983

1985 GetSuperClassSourceRange(FirstSuperInfo, FirstID),

1986 SuperClassType)

1987 << (bool)FirstSuperInfo << FirstType;

1988

1990 if (SecondSuperInfo)

1991 SecondType = SecondSuperInfo->getType();

1992

1994 GetSuperClassSourceRange(SecondSuperInfo, SecondID),

1995 SuperClassType)

1996 << (bool)SecondSuperInfo << SecondType;

1997 return true;

1998 }

1999

2000

2002 auto &SecondProtos = SecondDD->ReferencedProtocols;

2003 if (diagnoseSubMismatchProtocols(FirstProtos, FirstID, FirstModule,

2004 SecondProtos, SecondID, SecondModule))

2005 return true;

2006 }

2007

2008 auto PopulateHashes = [](DeclHashes &Hashes, const ObjCInterfaceDecl *ID,

2010 for (auto *D : ID->decls()) {

2012 continue;

2014 }

2015 };

2016

2017 DeclHashes FirstHashes;

2018 DeclHashes SecondHashes;

2019

2020

2021 PopulateHashes(FirstHashes, FirstID, FirstID->getDefinition());

2022 PopulateHashes(SecondHashes, SecondID, SecondID->getDefinition());

2023

2024 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);

2025 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;

2026 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;

2027 const Decl *FirstDecl = DR.FirstDecl;

2028 const Decl *SecondDecl = DR.SecondDecl;

2029

2030 if (FirstDiffType == Other || SecondDiffType == Other) {

2031 diagnoseSubMismatchUnexpected(DR, FirstID, FirstModule, SecondID,

2032 SecondModule);

2033 return true;

2034 }

2035

2036 if (FirstDiffType != SecondDiffType) {

2037 diagnoseSubMismatchDifferentDeclKinds(DR, FirstID, FirstModule, SecondID,

2038 SecondModule);

2039 return true;

2040 }

2041

2042 assert(FirstDiffType == SecondDiffType);

2043 switch (FirstDiffType) {

2044

2045 case EndOfClass:

2046 case Other:

2047

2048 case Field:

2049 case TypeDef:

2050 case Var:

2051

2052 case PublicSpecifer:

2053 case PrivateSpecifer:

2054 case ProtectedSpecifer:

2055 case StaticAssert:

2056 case CXXMethod:

2057 case TypeAlias:

2058 case Friend:

2059 case FunctionTemplate:

2060 llvm_unreachable("Invalid diff type");

2061

2062 case ObjCMethod: {

2063 if (diagnoseSubMismatchObjCMethod(FirstID, FirstModule, SecondModule,

2066 return true;

2067 break;

2068 }

2069 case ObjCIvar: {

2070 if (diagnoseSubMismatchField(FirstID, FirstModule, SecondModule,

2073 return true;

2074

2075

2081 IVarAccess)

2085 IVarAccess)

2086 << SecondIvar->getName()

2088 return true;

2089 }

2090 break;

2091 }

2092 case ObjCProperty: {

2093 if (diagnoseSubMismatchObjCProperty(FirstID, FirstModule, SecondModule,

2096 return true;

2097 break;

2098 }

2099 }

2100

2102 diag::err_module_odr_violation_mismatch_decl_unknown)

2103 << FirstID << FirstModule.empty() << FirstModule << FirstDiffType

2106 diag::note_module_odr_violation_mismatch_decl_unknown)

2107 << SecondModule.empty() << SecondModule << FirstDiffType

2109 return true;

2110}

2111

2115 const struct ObjCProtocolDecl::DefinitionData *SecondDD) const {

2116 if (FirstProtocol == SecondProtocol)

2117 return false;

2118

2121

2122 const ObjCProtocolDecl::DefinitionData *FirstDD = &FirstProtocol->data();

2123 assert(FirstDD && SecondDD && "Definitions without DefinitionData");

2124

2125 if (FirstDD != SecondDD) {

2126

2129 const ObjCProtocolList &SecondProtocols = SecondDD->ReferencedProtocols;

2130 if (diagnoseSubMismatchProtocols(FirstProtocols, FirstProtocol, FirstModule,

2131 SecondProtocols, SecondProtocol,

2132 SecondModule))

2133 return true;

2134 }

2135

2136 auto PopulateHashes = [](DeclHashes &Hashes, const ObjCProtocolDecl *ID,

2138 for (const Decl *D : ID->decls()) {

2140 continue;

2142 }

2143 };

2144

2145 DeclHashes FirstHashes;

2146 DeclHashes SecondHashes;

2147

2148

2149 PopulateHashes(FirstHashes, FirstProtocol, FirstProtocol->getDefinition());

2150 PopulateHashes(SecondHashes, SecondProtocol, SecondProtocol->getDefinition());

2151

2152 DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes);

2153 ODRMismatchDecl FirstDiffType = DR.FirstDiffType;

2154 ODRMismatchDecl SecondDiffType = DR.SecondDiffType;

2155 const Decl *FirstDecl = DR.FirstDecl;

2156 const Decl *SecondDecl = DR.SecondDecl;

2157

2158 if (FirstDiffType == Other || SecondDiffType == Other) {

2159 diagnoseSubMismatchUnexpected(DR, FirstProtocol, FirstModule,

2160 SecondProtocol, SecondModule);

2161 return true;

2162 }

2163

2164 if (FirstDiffType != SecondDiffType) {

2165 diagnoseSubMismatchDifferentDeclKinds(DR, FirstProtocol, FirstModule,

2166 SecondProtocol, SecondModule);

2167 return true;

2168 }

2169

2170 assert(FirstDiffType == SecondDiffType);

2171 switch (FirstDiffType) {

2172

2173 case EndOfClass:

2174 case Other:

2175

2176 case Field:

2177 case TypeDef:

2178 case Var:

2179 case ObjCIvar:

2180

2181 case PublicSpecifer:

2182 case PrivateSpecifer:

2183 case ProtectedSpecifer:

2184 case StaticAssert:

2185 case CXXMethod:

2186 case TypeAlias:

2187 case Friend:

2188 case FunctionTemplate:

2189 llvm_unreachable("Invalid diff type");

2190 case ObjCMethod: {

2191 if (diagnoseSubMismatchObjCMethod(FirstProtocol, FirstModule, SecondModule,

2194 return true;

2195 break;

2196 }

2197 case ObjCProperty: {

2198 if (diagnoseSubMismatchObjCProperty(FirstProtocol, FirstModule,

2199 SecondModule,

2202 return true;

2203 break;

2204 }

2205 }

2206

2208 diag::err_module_odr_violation_mismatch_decl_unknown)

2209 << FirstProtocol << FirstModule.empty() << FirstModule << FirstDiffType

2212 diag::note_module_odr_violation_mismatch_decl_unknown)

2213 << SecondModule.empty() << SecondModule << FirstDiffType

2215 return true;

2216}

Defines the C++ template declaration subclasses.

static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)

Produce a diagnostic highlighting some portion of a literal.

llvm::MachO::Record Record

Defines the clang::Module class, which describes a module in the source code.

static unsigned computeODRHash(QualType Ty)

Definition ODRDiagsEmitter.cpp:18

static bool diagnoseSubMismatchMethodParameters(DiagnosticsEngine &Diags, const NamedDecl *FirstContainer, StringRef FirstModule, StringRef SecondModule, const MethodT *FirstMethod, const MethodT *SecondMethod)

Definition ODRDiagsEmitter.cpp:53

This file contains the declaration of the ODRHash class, which calculates a hash based on AST nodes,...

Represents a base class of a C++ class.

AccessSpecifier getAccessSpecifierAsWritten() const

Retrieves the access specifier as written in the source code (which may mean that no access specifier...

bool isVirtual() const

Determines whether the base class is a virtual base class (or not).

QualType getType() const

Retrieves the type of the base class.

SourceRange getSourceRange() const LLVM_READONLY

Retrieves the source range that contains the entire base specifier.

Represents a static or instance method of a struct/union/class.

Represents a C++ struct/union/class.

ClassTemplateDecl * getDescribedClassTemplate() const

Retrieves the class template that is described by this class declaration.

Declaration of a class template.

Represents a pointer type decayed from an array or function type.

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

Decl - This represents one declaration (or definition), e.g.

SourceLocation getEndLoc() const LLVM_READONLY

Module * getImportedOwningModule() const

Get the imported owning module, if this decl is from an imported (non-local) module.

SourceLocation getLocation() const

SourceLocation getBeginLoc() const LLVM_READONLY

virtual SourceRange getSourceRange() const LLVM_READONLY

Source range that this declaration covers.

The name of a declaration.

IdentifierInfo * getAsIdentifierInfo() const

Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...

bool isIdentifier() const

Predicate functions for querying what type of name this is.

Concrete class used by the front-end to report problems and issues.

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

An instance of this object exists for each enum constant that is defined.

const Expr * getInitExpr() const

bool isScoped() const

Returns true if this is a C++11 scoped enumeration.

bool isScopedUsingClassTag() const

Returns true if this is a C++11 scoped enumeration.

TypeSourceInfo * getIntegerTypeSourceInfo() const

Return the type source info for the underlying integer type, if no type source info exists,...

SourceRange getSourceRange() const override LLVM_READONLY

Overrides to provide correct range when there's an enum-base specifier with forward declarations.

This represents one expression.

Represents a member of a struct/union/class.

bool isMutable() const

Determines whether this field is mutable (C++ only).

Expr * getInClassInitializer() const

Get the C++11 default member initializer for this member, or null if one has not been set.

bool isBitField() const

Determines whether this field is a bitfield.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

Expr * getBitWidth() const

Returns the expression that represents the bit width, if this field is a bit field.

FriendDecl - Represents the declaration of a friend entity, which can be a function,...

SourceLocation getFriendLoc() const

Retrieves the location of the 'friend' keyword.

SourceRange getSourceRange() const override LLVM_READONLY

Retrieves the source range for the friend declaration.

NamedDecl * getFriendDecl() const

If this friend declaration doesn't name a type, return the inner declaration.

TypeSourceInfo * getFriendType() const

If this friend declaration names an (untemplated but possibly dependent) type, return the type; other...

Represents a function declaration or definition.

const ParmVarDecl * getParamDecl(unsigned i) const

SourceRange getReturnTypeSourceRange() const

Attempt to compute an informative source range covering the function return type.

QualType getReturnType() const

bool isExplicitlyDefaulted() const

Whether this function is explicitly defaulted.

const TemplateArgumentList * getTemplateSpecializationArgs() const

Retrieve the template arguments used to produce this function template specialization from the primar...

unsigned getODRHash()

Returns ODRHash of the function.

StorageClass getStorageClass() const

Returns the storage class as written in the source.

bool isDeletedAsWritten() const

bool isPureVirtual() const

Whether this virtual function is pure, i.e.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

bool isVirtualAsWritten() const

Whether this function is marked as virtual explicitly.

size_t param_size() const

bool isInlineSpecified() const

Determine whether the "inline" keyword was specified for this function.

Declaration of a template function.

StringRef getName() const

Return the actual identifier string.

Describes a module or submodule.

This represents a decl that may have a name.

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

DeclarationName getDeclName() const

Get the actual, stored name of the declaration, which may be a special name.

NonTypeTemplateParmDecl - Declares a non-type template parameter, e.g., "Size" in.

bool hasDefaultArgument() const

Determine whether this template parameter has a default argument.

bool defaultArgumentWasInherited() const

Determines whether the default argument was inherited from a previous declaration of this template.

const TemplateArgumentLoc & getDefaultArgument() const

Retrieve the default argument, if any.

bool isParameterPack() const

Whether this parameter is a non-type template parameter pack.

bool diagnoseMismatch(const FunctionDecl *FirstFunction, const FunctionDecl *SecondFunction) const

Diagnose ODR mismatch between 2 FunctionDecl.

Definition ODRDiagsEmitter.cpp:1659

static std::string getOwningModuleNameForDiagnostic(const Decl *D)

Get the best name we know for the module that owns the given declaration, or an empty string if the d...

Definition ODRDiagsEmitter.cpp:43

void AddStmt(const Stmt *S)

void AddFunctionDecl(const FunctionDecl *Function, bool SkipBody=false)

void AddSubDecl(const Decl *D)

void AddQualType(QualType T)

void AddTemplateParameterList(const TemplateParameterList *TPL)

void AddTemplateArgument(TemplateArgument TA)

static bool isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent)

ObjCContainerDecl - Represents a container for method declarations.

Represents an ObjC class declaration.

unsigned getODRHash()

Get precomputed ODRHash or add a new one.

const ObjCProtocolList & getReferencedProtocols() const

ObjCInterfaceDecl * getSuperClass() const

ObjCInterfaceDecl * getDefinition()

Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...

TypeSourceInfo * getSuperClassTInfo() const

ObjCIvarDecl - Represents an ObjC instance variable.

AccessControl getCanonicalAccessControl() const

ObjCMethodDecl - Represents an instance or class method declaration.

bool isDirectMethod() const

True if the method is tagged as objc_direct.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

bool isInstanceMethod() const

bool isThisDeclarationADesignatedInitializer() const

Returns true if this specific method declaration is marked with the designated initializer attribute.

QualType getReturnType() const

ObjCImplementationControl getImplementationControl() const

Represents one property declaration in an Objective-C interface.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

SourceLocation getLParenLoc() const

ObjCPropertyAttribute::Kind getPropertyAttributesAsWritten() const

ObjCPropertyAttribute::Kind getPropertyAttributes() const

PropertyControl getPropertyImplementation() const

Represents an Objective-C protocol declaration.

const ObjCProtocolList & getReferencedProtocols() const

ObjCProtocolDecl * getDefinition()

Retrieve the definition of this protocol, if any.

A list of Objective-C protocols, along with the source locations at which they were referenced.

loc_iterator loc_begin() const

Represents a parameter to a function.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

Represents a struct/union/class.

Encodes a location in the source.

A trivial tuple used to represent a source range.

SourceLocation getBegin() const

Represents a C++11 static_assert declaration.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

Stmt - This represents one statement.

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

SourceLocation getBeginLoc() const LLVM_READONLY

A template argument list.

const TemplateArgument & getArgument() const

Represents a template argument.

@ Pack

The template argument is actually a parameter pack.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

TemplateParameterList * getTemplateParameters() const

Get the list of template parameters.

Stores a list of template parameters for a TemplateDecl and its derived classes.

NamedDecl * getParam(unsigned Idx)

ArrayRef< NamedDecl * > asArray()

TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.

const TemplateArgumentLoc & getDefaultArgument() const

Retrieve the default argument, if any.

bool isParameterPack() const

Whether this template template parameter is a template parameter pack.

bool defaultArgumentWasInherited() const

Determines whether the default argument was inherited from a previous declaration of this template.

bool hasDefaultArgument() const

Determine whether this template parameter has a default argument.

Declaration of a template type parameter.

const TemplateArgumentLoc & getDefaultArgument() const

Retrieve the default argument, if any.

bool hasDefaultArgument() const

Determine whether this template parameter has a default argument.

bool defaultArgumentWasInherited() const

Determines whether the default argument was inherited from a previous declaration of this template.

bool isParameterPack() const

Returns whether this is a parameter pack.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

Base wrapper for a particular "section" of type source info.

SourceLocation getEndLoc() const

Get the end source location.

SourceLocation getBeginLoc() const

Get the begin source location.

A container of type source information.

TypeLoc getTypeLoc() const

Return the TypeLoc wrapper for the type source info.

QualType getType() const

Return the type wrapped by this type source info.

const T * castAs() const

Member-template castAs.

const T * getAs() const

Member-template getAs'.

Base class for declarations which introduce a typedef-name.

QualType getUnderlyingType() const

Represents a variable declaration or definition.

bool isConstexpr() const

Whether this variable is (C++11) constexpr.

SourceRange getSourceRange() const override LLVM_READONLY

Source range that this declaration covers.

const Expr * getInit() const

std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl

All declarations that can appear in a module declaration.

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

StorageClass

Storage classes.

@ Type

The name was classified as a type.

@ NumObjCPropertyAttrsBits

Number of bits fitting all the property attributes.

U cast(CodeGen::Address addr)

@ Enum

The "enum" keyword introduces the elaborated-type-specifier.