clang: lib/Sema/SemaAccess.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

24#include "llvm/ADT/STLForwardCompat.h"

25

26using namespace clang;

27using namespace sema;

28

29

35

39 if (!PrevMemberDecl) {

40

42 return false;

43 }

44

45

46

47 if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {

49 diag::err_class_redeclared_with_different_access)

50 << MemberDecl << LexicalAS;

51 Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)

52 << PrevMemberDecl << PrevMemberDecl->getAccess();

53

55 return true;

56 }

57

59 return false;

60}

61

64

65

66

67 if (isa(DC))

68 DC = cast(DC)->getDeclContext();

69

70 CXXRecordDecl *DeclaringClass = cast(DC);

72 DeclaringClass = cast(DeclaringClass->getDeclContext());

73 return DeclaringClass;

74}

75

76namespace {

77struct EffectiveContext {

78 EffectiveContext() : Inner(nullptr), Dependent(false) {}

79

80 explicit EffectiveContext(DeclContext *DC)

81 : Inner(DC),

82 Dependent(DC->isDependentContext()) {

83

84

85

86

87 if (auto *DGD = dyn_cast(DC)) {

88 if (DGD->isImplicit()) {

89 DC = DGD->getCorrespondingConstructor();

90 if (!DC) {

91

92

93 DC = cast(DGD->getDeducedTemplate()->getTemplatedDecl());

94 }

95 }

96 }

97

98

99

100

101

102

103

104

105

106

107

108

109

110 while (true) {

111

112

113

114

115

116

117 if (isa(DC)) {

120 DC = Record->getDeclContext();

121 } else if (isa(DC)) {

123 Functions.push_back(Function->getCanonicalDecl());

124 if (Function->getFriendObjectKind())

125 DC = Function->getLexicalDeclContext();

126 else

127 DC = Function->getDeclContext();

129 break;

130 } else {

132 }

133 }

134 }

135

136 bool isDependent() const { return Dependent; }

137

138 bool includesClass(const CXXRecordDecl *R) const {

140 return llvm::is_contained(Records, R);

141 }

142

143

144

146 return Inner;

147 }

148

150

155};

156

157

158

163 }

164

166 MemberNonce _,

171 FoundDecl, BaseObjectType) {

173 }

174

176 BaseNonce _,

180 : AccessedEntity(Context.getDiagAllocator(), Base, BaseClass, DerivedClass,

181 Access) {

183 }

184

185 bool isInstanceMember() const {

186 return (isMemberAccess() && getTargetDecl()->isCXXInstanceMember());

187 }

188

189 bool hasInstanceContext() const {

190 return HasInstanceContext;

191 }

192

193 class SavedInstanceContext {

194 public:

195 SavedInstanceContext(SavedInstanceContext &&S)

197 S.Target = nullptr;

198 }

199

200

201

202 SavedInstanceContext &operator=(SavedInstanceContext &&) = delete;

203

204

205

206 SavedInstanceContext(const SavedInstanceContext &) = delete;

207 SavedInstanceContext &operator=(const SavedInstanceContext &) = delete;

208

209 ~SavedInstanceContext() {

211 Target->HasInstanceContext = Has;

212 }

213

214 private:

215 friend struct AccessTarget;

216 explicit SavedInstanceContext(AccessTarget &Target)

218 AccessTarget *Target;

219 bool Has;

220 };

221

222 SavedInstanceContext saveInstanceContext() {

223 return SavedInstanceContext(*this);

224 }

225

226 void suppressInstanceContext() {

227 HasInstanceContext = false;

228 }

229

231 assert(HasInstanceContext);

232 if (CalculatedInstanceContext)

233 return InstanceContext;

234

235 CalculatedInstanceContext = true;

237 InstanceContext = (IC ? cast(IC)->getCanonicalDecl()

238 : nullptr);

239 return InstanceContext;

240 }

241

243 return DeclaringClass;

244 }

245

246

247

248 const CXXRecordDecl *getEffectiveNamingClass() const {

249 const CXXRecordDecl *namingClass = getNamingClass();

251 namingClass = cast(namingClass->getParent());

253 }

254

255private:

257 HasInstanceContext = (isMemberAccess() &&

258 !getBaseObjectType().isNull() &&

259 getTargetDecl()->isCXXInstanceMember());

260 CalculatedInstanceContext = false;

261 InstanceContext = nullptr;

262

263 if (isMemberAccess())

265 else

266 DeclaringClass = getBaseClass();

267 DeclaringClass = DeclaringClass->getCanonicalDecl();

268 }

269

270 bool HasInstanceContext : 1;

271 mutable bool CalculatedInstanceContext : 1;

274};

275

276}

277

278

281

283 return false;

284

287 if (FromDC == ToDC) return true;

289

290

291 return true;

292}

293

294

295

296

297

298

302 assert(Target->getCanonicalDecl() == Target);

303

305

309

312

313 while (true) {

317

318 for (const auto &I : Derived->bases()) {

320

323 RD = cast(RT->getDecl());

326 RD = IT->getDecl();

327 } else {

328 assert(T->isDependentType() && "non-dependent base wasn't a record?");

330 continue;

331 }

332

337

338 Queue.push_back(RD);

339 }

340

341 if (Queue.empty()) break;

342

343 Derived = Queue.pop_back_val();

344 }

345

346 return OnFailure;

347}

348

349

352 if (Friend == Context)

353 return true;

354

355 assert(Friend->isDependentContext() &&

356 "can't handle friends with dependent contexts here");

357

358 if (!Context->isDependentContext())

359 return false;

360

361 if (Friend->isFileContext())

362 return false;

363

364

365 return true;

366}

367

368

369

371 if (Friend == Context)

372 return true;

373

374 if (Friend->isDependentType() && !Context->isDependentType())

375 return false;

376

377

378 return true;

379}

380

384 if (Context->getDeclName() != Friend->getDeclName())

385 return false;

386

388 Context->getDeclContext(),

389 Friend->getDeclContext()))

390 return false;

391

397 ->getAs();

398

399

400

401 if (FriendTy.getQualifiers() != ContextTy.getQualifiers())

402 return false;

403

404 if (FriendTy->getNumParams() != ContextTy->getNumParams())

405 return false;

406

408 FriendTy->getReturnType()))

409 return false;

410

411 for (unsigned I = 0, E = FriendTy->getNumParams(); I != E; ++I)

413 FriendTy->getParamType(I)))

414 return false;

415

416 return true;

417}

418

423 Context->getTemplatedDecl(),

424 Friend->getTemplatedDecl());

425}

426

428 const EffectiveContext &EC,

430 if (EC.includesClass(Friend))

432

433 if (EC.isDependent()) {

434 for (const CXXRecordDecl *Context : EC.Records) {

437 }

438 }

439

441}

442

444 const EffectiveContext &EC,

447 return MatchesFriend(S, EC, cast(RT->getDecl()));

448

449

450 if (Friend->isDependentType())

452

454}

455

456

457

459 const EffectiveContext &EC,

462

463

464

466 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {

468

469

471

472

473 if (isa(Record)) {

474 CTD = cast(Record)

475 ->getSpecializedTemplate();

476

477

478 } else {

479 CTD = Record->getDescribedClassTemplate();

480 if (!CTD) continue;

481 }

482

483

486

487

488 if (!EC.isDependent())

489 continue;

490

491

492

494 continue;

495

496

497

499 Friend->getDeclContext()))

500 continue;

501

502

504 }

505

506 return OnFailure;

507}

508

509

510

512 const EffectiveContext &EC,

515

517 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {

520

523 }

524

525 return OnFailure;

526}

527

528

529

531 const EffectiveContext &EC,

534

536

538 I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) {

539

541 if (!FTD)

542 FTD = (*I)->getDescribedFunctionTemplate();

543 if (!FTD)

544 continue;

545

547

550

553 }

554

555 return OnFailure;

556}

557

558

559

561 const EffectiveContext &EC,

563

564

567

570

573

574

575

576 if (isa(Friend))

578

579 if (isa(Friend))

581

582 if (isa(Friend))

584

585 assert(isa(Friend) && "unknown friend decl kind");

587}

588

590 const EffectiveContext &EC,

593

594

599

601 continue;

602

605 break;

606 }

607 }

608

609

610 return OnFailure;

611}

612

613namespace {

614

615

616

617struct ProtectedFriendContext {

619 const EffectiveContext &EC;

621 bool CheckDependent;

622 bool EverDependent;

623

624

626

627 ProtectedFriendContext(Sema &S, const EffectiveContext &EC,

630 : S(S), EC(EC), NamingClass(NamingClass),

631 CheckDependent(InstanceContext->isDependentContext() ||

632 NamingClass->isDependentContext()),

633 EverDependent(false) {}

634

635

636

637 bool checkFriendshipAlongPath(unsigned I) {

638 assert(I < CurPath.size());

639 for (unsigned E = CurPath.size(); I != E; ++I) {

643 case AR_dependent: EverDependent = true; continue;

644 }

645 }

646 return false;

647 }

648

649

650

651

652

653

654 bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) {

655

656

657

658 if (Cur == NamingClass)

659 return checkFriendshipAlongPath(PrivateDepth);

660

662 EverDependent = true;

663

664

665 for (const auto &I : Cur->bases()) {

666

667

668 unsigned BasePrivateDepth = PrivateDepth;

669 if (I.getAccessSpecifier() == AS_private)

670 BasePrivateDepth = CurPath.size() - 1;

671

673

676 RD = cast(RT->getDecl());

679 RD = IT->getDecl();

680 } else {

681 assert(T->isDependentType() && "non-dependent base wasn't a record?");

682 EverDependent = true;

683 continue;

684 }

685

686

687 CurPath.push_back(RD);

688 if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth))

689 return true;

690 CurPath.pop_back();

691 }

692

693 return false;

694 }

695

697 assert(CurPath.empty());

698 CurPath.push_back(Cur);

699 return findFriendship(Cur, 0);

700 }

701};

702}

703

704

705

706

707

708

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

733 assert(InstanceContext == nullptr ||

736

737

738

739

740 if (!InstanceContext) return GetFriendKind(S, EC, NamingClass);

741

742 ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass);

743 if (PRC.findFriendship(InstanceContext)) return AR_accessible;

746}

747

749 const EffectiveContext &EC,

752 const AccessTarget &Target) {

754 "declaration should be canonicalized before being passed here");

755

758

760

761 for (EffectiveContext::record_iterator

762 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {

763

764

766

767

769 if (ECRecord == NamingClass)

771

774

775

776 } else {

782 }

783

784

785

786

787

788

789

790

791

792

793

794

795

796

797

798

799

800

801 if (Target.hasInstanceContext()) {

802

804

805

806

807

808

809

810

811

812 if (S.getLangOpts().MSVCCompat && !EC.Functions.empty())

813 if (CXXMethodDecl* MD = dyn_cast(EC.Functions.front()))

815

816

817

818

819

820

821

822

823

824

825

826

827

828

829

830

831

832 if (NamingClass == ECRecord) return AR_accessible;

833

834

835 continue;

836 }

837

838 assert(Target.isInstanceMember());

839

841 if (!InstanceContext) {

843 continue;

844 }

845

850 }

851 }

852 }

853

854

855

856

857

858

859

860

861

862

863

865

867 if (Target.hasInstanceContext()) {

868 InstanceContext = Target.resolveInstanceContext(S);

870 }

871

876 }

877 llvm_unreachable("impossible friendship kind");

878 }

879

884 }

885

886

887 llvm_unreachable("impossible friendship kind");

888}

889

890

891

892

893

894

895

896

897

898

899

900

901

902

903

904

905

906

907

908

909

910

911

912

913

914

915

916

917

918

919

920

921

922

923

924

925

926

927

928

929

930

931

932

933

934

935

936

937

938

939

940

941

942

943

944

945

947 const EffectiveContext &EC,

948 AccessTarget &Target,

951

954

955

957 Paths);

958 assert(isDerived && "derived class not actually derived from base");

959 (void) isDerived;

960

962

963 assert(FinalAccess != AS_none && "forbidden access after declaring class");

964

965 bool AnyDependent = false;

966

967

969 PI != PE; ++PI) {

970 AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext();

971

972

974 CXXBasePath::iterator I = PI->end(), E = PI->begin();

975 while (I != E) {

976 --I;

977

978 assert(PathAccess != AS_none);

979

980

981

982

985 break;

986 }

987

989

990 AccessSpecifier BaseAccess = I->Base->getAccessSpecifier();

991 PathAccess = std::max(PathAccess, BaseAccess);

992

997

998

999

1000 Target.suppressInstanceContext();

1001 break;

1003 AnyDependent = true;

1004 goto Next;

1005 }

1006 }

1007

1008

1009

1010 if (BestPath == nullptr || PathAccess < BestPath->Access) {

1011 BestPath = &*PI;

1012 BestPath->Access = PathAccess;

1013

1014

1016 return BestPath;

1017 }

1018

1019 Next: ;

1020 }

1021

1023 "fell out of loop with public path");

1024

1025

1026

1027 if (AnyDependent)

1028 return nullptr;

1029

1030 return BestPath;

1031}

1032

1033

1034

1035

1036

1037

1039 AccessTarget &Target) {

1040

1041 if (Target.isInstanceMember())

1042 return false;

1043

1044 assert(Target.isMemberAccess());

1045

1047

1048 for (EffectiveContext::record_iterator

1049 I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) {

1055 }

1056

1057

1058

1059

1060

1061

1062

1063

1064

1066

1067

1068

1069 if (Target.hasInstanceContext()) {

1070

1071 if (NamingClass == ECRecord) continue;

1072

1073

1074

1075 S.Diag(D->getLocation(), diag::note_access_protected_restricted_noobject)

1077 return true;

1078 }

1079

1080 const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S);

1081 assert(InstanceContext && "diagnosing dependent access");

1082

1087 break;

1088 }

1089

1090

1091

1092

1093 if (isa(D) || isa(D) ||

1094 (isa(D) &&

1095 isa(

1096 cast(D)->getTemplatedDecl()))) {

1098 diag::note_access_protected_restricted_ctordtor)

1100 }

1101

1102

1104 diag::note_access_protected_restricted_object)

1106 }

1107

1108 return false;

1109}

1110

1111

1112

1114 const EffectiveContext &EC,

1115 AccessTarget &entity) {

1116 assert(entity.isMemberAccess());

1117 NamedDecl *D = entity.getTargetDecl();

1118

1121 return;

1122

1123

1126 if (VarDecl *VD = dyn_cast(D))

1128 else if (FunctionDecl *FD = dyn_cast(D))

1130 else if (TypedefNameDecl *TND = dyn_cast(D))

1132 else if (TagDecl *TD = dyn_cast(D)) {

1133 if (isa(D) && cast(D)->isInjectedClassName())

1134 break;

1136 }

1137 if (!PrevDecl) break;

1138 D = PrevDecl;

1139 }

1140

1142 Decl *ImmediateChild;

1144 ImmediateChild = D;

1145 else {

1147 while (DC->getParent() != DeclaringClass)

1149 ImmediateChild = cast(DC);

1150 }

1151

1152

1153

1154 bool isImplicit = true;

1155 for (const auto *I : DeclaringClass->decls()) {

1156 if (I == ImmediateChild) break;

1157 if (isa(I)) {

1158 isImplicit = false;

1159 break;

1160 }

1161 }

1162

1165 << isImplicit;

1166}

1167

1168

1169

1171 const EffectiveContext &EC,

1172 AccessTarget &entity) {

1173

1174 AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext();

1175

1176

1177

1178

1179

1181

1182

1183 if (entity.isMemberAccess()) {

1184 NamedDecl *D = entity.getTargetDecl();

1186 const CXXRecordDecl *declaringClass = entity.getDeclaringClass();

1187

1188 switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) {

1189

1190

1193 entity.suppressInstanceContext();

1194 break;

1195

1198 declaringClass == entity.getEffectiveNamingClass())

1200 break;

1201

1203 llvm_unreachable("cannot diagnose dependent access");

1204 }

1205 }

1206

1210

1211 CXXBasePath::iterator i = path.end(), e = path.begin();

1212 CXXBasePath::iterator constrainingBase = i;

1213 while (i != e) {

1214 --i;

1215

1217

1218

1219

1222

1223

1224

1226 if (baseAccess > accessSoFar) {

1227 constrainingBase = i;

1228 accessSoFar = baseAccess;

1229 }

1230

1231 switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) {

1235 entity.suppressInstanceContext();

1236 constrainingBase = nullptr;

1237 break;

1239 llvm_unreachable("cannot diagnose dependent access");

1240 }

1241

1242

1243

1246 assert(constrainingBase == i);

1247 break;

1248 }

1249 }

1250

1251

1252

1253 if (constrainingBase == path.end())

1255

1256

1257

1258

1259 unsigned diagnostic;

1260 if (entity.isMemberAccess() ||

1261 constrainingBase + 1 != path.end()) {

1262 diagnostic = diag::note_access_constrained_by_path;

1263 } else {

1264 diagnostic = diag::note_access_natural;

1265 }

1266

1268

1273

1274 if (entity.isMemberAccess())

1275 S.Diag(entity.getTargetDecl()->getLocation(),

1276 diag::note_member_declared_at);

1277}

1278

1280 const EffectiveContext &EC,

1281 AccessTarget &Entity) {

1282 const CXXRecordDecl *NamingClass = Entity.getNamingClass();

1283 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();

1284 NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : nullptr);

1285

1286 S.Diag(Loc, Entity.getDiag())

1292}

1293

1294

1295

1296

1297

1298

1299

1300

1301

1302

1303

1304

1305

1306

1307

1308

1309

1310

1311

1312

1313

1316 AccessTarget &Entity) {

1318 dyn_cast(Entity.getTargetDecl()))

1319 if (UsingDecl *UD = dyn_cast(Shadow->getIntroducer())) {

1321 if (Entity.getTargetDecl()->getAccess() == AS_private &&

1324 S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)

1325 << UD->getQualifiedNameAsString()

1327 return true;

1328 }

1329 }

1330 return false;

1331}

1332

1333

1334

1336 const EffectiveContext &EC,

1337 AccessTarget &Entity) {

1338

1339 const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass();

1340

1342 assert(UnprivilegedAccess != AS_public && "public access not weeded out");

1343

1344

1345

1346

1347

1348 if (UnprivilegedAccess != AS_none) {

1349 switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) {

1351

1352

1353

1354

1355

1356

1357

1359

1362 }

1363 }

1364

1365 AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext();

1366

1367

1368

1370

1371 if (Entity.isMemberAccess()) {

1372

1373

1375 const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass();

1376

1378 switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) {

1380

1381

1382

1383

1384

1386 Entity.suppressInstanceContext();

1387 break;

1390 }

1391

1392 if (DeclaringClass == NamingClass)

1394 } else {

1396 }

1397

1398 assert(Entity.getDeclaringClass() != NamingClass);

1399

1400

1405

1406 assert(Path->Access <= UnprivilegedAccess &&

1407 "access along best path worse than direct?");

1411}

1412

1414 const EffectiveContext &EC,

1416 const AccessTarget &Entity) {

1417 assert(EC.isDependent() && "delaying non-dependent access");

1419 assert(DC->isDependentContext() && "delaying non-dependent access");

1422 Entity.isMemberAccess(),

1423 Entity.getAccess(),

1424 Entity.getTargetDecl(),

1425 Entity.getNamingClass(),

1426 Entity.getBaseObjectType(),

1427 Entity.getDiag());

1428}

1429

1430

1432 const EffectiveContext &EC,

1434 AccessTarget &Entity) {

1435 assert(Entity.getAccess() != AS_public && "called for public access!");

1436

1441

1446 if (!Entity.isQuiet())

1449

1452 }

1453

1454

1455 llvm_unreachable("invalid access result");

1456}

1457

1459 AccessTarget &Entity) {

1460

1461 if (Entity.getAccess() == AS_public)

1463

1464

1465

1466

1467

1468

1469

1470

1471

1472

1473

1474

1475

1476

1477

1478

1479

1480

1482

1483

1484

1485

1486

1487

1489 bool IsFriendDeclaration = false;

1490 while (TS && !IsFriendDeclaration) {

1493 }

1494 if (!IsFriendDeclaration) {

1497 }

1498 }

1499

1505 }

1506 llvm_unreachable("invalid access result");

1507}

1508

1510

1511

1512

1513

1514

1518 } else if (FunctionDecl *FN = dyn_cast(D)) {

1519 DC = FN;

1520 } else if (TemplateDecl *TD = dyn_cast(D)) {

1521 if (isa(TD->getTemplatedDecl()))

1522 DC = cast(TD->getTemplatedDecl());

1523 } else if (auto *RD = dyn_cast(D)) {

1524 DC = RD;

1525 }

1526

1527 EffectiveContext EC(DC);

1528

1530

1533}

1534

1539

1541 TemplateArgs);

1542 if (!NamingD) return;

1544 TemplateArgs);

1545 if (!TargetD) return;

1546

1548 CXXRecordDecl *NamingClass = cast(NamingD);

1549 NamedDecl *TargetDecl = cast(TargetD);

1551 if (!BaseObjectType.isNull()) {

1552 BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc,

1554 if (BaseObjectType.isNull()) return;

1555 }

1556

1557 AccessTarget Entity(Context,

1558 AccessTarget::Member,

1559 NamingClass,

1561 BaseObjectType);

1564 } else {

1565 AccessTarget Entity(Context,

1566 AccessTarget::Base,

1567 cast(TargetD),

1568 cast(NamingD),

1569 Access);

1572 }

1573}

1574

1578 E->getNamingClass() ||

1581

1582 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),

1584 Entity.setDiag(diag::err_access) << E->getSourceRange();

1585

1586 return CheckAccess(*this, E->getNameLoc(), Entity);

1587}

1588

1594

1595 QualType BaseType = E->getBaseType();

1596 if (E->isArrow())

1598

1599 AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(),

1600 Found, BaseType);

1601 Entity.setDiag(diag::err_access) << E->getSourceRange();

1602

1603 return CheckAccess(*this, E->getMemberLoc(), Entity);

1604}

1605

1611

1613 return true;

1614

1615 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,

1616 ObjectType);

1617

1618

1619 Entity.setDiag(Diag);

1620

1624 case AR_dependent: llvm_unreachable("dependent for =delete computation");

1625 case AR_delayed: llvm_unreachable("cannot delay =delete computation");

1626 }

1627 llvm_unreachable("bad access result");

1628}

1629

1636

1637

1641

1644

1645 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,

1647 ObjectTy);

1648 Entity.setDiag(PDiag);

1649

1651}

1652

1657 bool IsCopyBindingRefToTemp) {

1660

1662 switch (Entity.getKind()) {

1663 default:

1664 PD = PDiag(IsCopyBindingRefToTemp

1665 ? diag::ext_rvalue_to_reference_access_ctor

1666 : diag::err_access_ctor);

1667

1668 break;

1669

1671 PD = PDiag(diag::err_access_base_ctor);

1675 break;

1676

1680 PD = PDiag(diag::err_access_field_ctor);

1681 PD << Field->getType()

1683 break;

1684 }

1685

1688 PD = PDiag(diag::err_access_lambda_capture);

1689 PD << VarName << Entity.getType()

1691 break;

1692 }

1693

1694 }

1695

1697}

1698

1707

1708 CXXRecordDecl *NamingClass = Constructor->getParent();

1709

1710

1711

1712

1713

1714

1715

1716

1722 } else if (auto *Shadow =

1723 dyn_cast(Found.getDecl())) {

1724

1725

1726 ObjectClass = Shadow->getParent();

1727 } else {

1728 ObjectClass = NamingClass;

1729 }

1730

1731 AccessTarget AccessEntity(

1732 Context, AccessTarget::Member, NamingClass,

1735 AccessEntity.setDiag(PD);

1736

1737 return CheckAccess(*this, UseLoc, AccessEntity);

1738}

1739

1744 bool Diagnose) {

1746 !NamingClass ||

1749

1750 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,

1753 Entity.setDiag(diag::err_access)

1754 << PlacementRange;

1755

1756 return CheckAccess(*this, OpLoc, Entity);

1757}

1758

1763 !NamingClass ||

1766

1767 AccessTarget Entity(Context, AccessTarget::Member, NamingClass,

1769

1770 return CheckAccess(*this, UseLoc, Entity);

1771}

1772

1780

1781 AccessTarget Entity(Context, AccessTarget::Member, DecomposedClass, Field,

1783 Entity.setDiag(diag::err_decomp_decl_inaccessible_field);

1784

1785 return CheckAccess(*this, UseLoc, Entity);

1786}

1787

1789 Expr *ObjectExpr,

1794

1797

1798 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,

1800 Entity.setDiag(diag::err_access) << ObjectExpr->getSourceRange() << Range;

1801

1802 return CheckAccess(*this, OpLoc, Entity);

1803}

1804

1806 Expr *ObjectExpr,

1807 Expr *ArgExpr,

1812}

1813

1815 Expr *ObjectExpr,

1819 if (!ArgExprs.empty()) {

1820 R = SourceRange(ArgExprs.front()->getBeginLoc(),

1821 ArgExprs.back()->getEndLoc());

1822 }

1823

1825}

1826

1828 assert(isa(target->getAsFunction()));

1829

1830

1831

1833

1836

1838

1839 AccessTarget entity(Context, AccessTarget::Member,

1842 QualType());

1843 entity.setDiag(diag::err_access_friend_function)

1846

1847

1848

1854 }

1855 llvm_unreachable("invalid access result");

1856}

1857

1864

1867

1868 AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found,

1869 QualType());

1870 Entity.setDiag(diag::err_access)

1872

1874}

1875

1880 unsigned DiagID,

1881 bool ForceCheck,

1882 bool ForceUnprivileged) {

1883 if (!ForceCheck && getLangOpts().AccessControl)

1885

1888

1892

1893 AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD,

1894 Path.Access);

1895 if (DiagID)

1896 Entity.setDiag(DiagID) << Derived << Base;

1897

1898 if (ForceUnprivileged) {

1900 AccessLoc, Entity)) {

1904 }

1905 llvm_unreachable("unexpected result from CheckEffectiveAccess");

1906 }

1907 return CheckAccess(*this, AccessLoc, Entity);

1908}

1909

1912 && "performing access check without access control");

1913 assert(R.getNamingClass() && "performing access check without naming class");

1914

1916 if (I.getAccess() != AS_public) {

1920 Entity.setDiag(diag::err_access);

1922 }

1923 }

1924}

1925

1928

1929 if (Target->isCXXClassMember() && NamingClass) {

1931 return false;

1932

1933

1934

1935

1940 }

1941

1943

1946 return true;

1947

1948

1949

1952 ClassOfMethodDecl = MD->getClassInterface();

1955 = dyn_cast(FD->getLexicalDeclContext())) {

1957 = dyn_cast(Impl))

1958 ClassOfMethodDecl = IMPD->getClassInterface();

1960 = dyn_cast(Impl))

1961 ClassOfMethodDecl = CatImplClass->getClassInterface();

1962 }

1963 }

1964

1965

1966 if (!ClassOfMethodDecl)

1967 return false;

1968

1969

1970 if (declaresSameEntity(ClassOfMethodDecl, Ivar->getContainingInterface()))

1971 return true;

1972

1973

1975 return false;

1976

1977 return Ivar->getContainingInterface()->isSuperClassOf(ClassOfMethodDecl);

1978 }

1979

1980 return true;

1981}

Defines the clang::ASTContext interface.

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the classes clang::DelayedDiagnostic and clang::AccessedEntity.

Defines the clang::Expr interface and subclasses for C++ expressions.

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::Target Target

llvm::MachO::Records Records

llvm::MachO::Record Record

static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, const EffectiveContext &EC, AccessTarget &Entity)

AccessResult

A copy of Sema's enum without AR_delayed.

static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, AccessTarget &Target)

Given that an entity has protected natural access, check whether access might be denied because of th...

static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, const CXXRecordDecl *Target)

Checks whether one class is derived from another, inclusively.

static void diagnoseBadDirectAccess(Sema &S, const EffectiveContext &EC, AccessTarget &entity)

We are unable to access a given declaration due to its direct access control; diagnose that.

static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, AccessTarget &Entity)

static AccessResult GetFriendKind(Sema &S, const EffectiveContext &EC, const CXXRecordDecl *Class)

static AccessResult MatchesFriend(Sema &S, const EffectiveContext &EC, const CXXRecordDecl *Friend)

static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC, const CXXRecordDecl *InstanceContext, const CXXRecordDecl *NamingClass)

Search for a class P that EC is a friend of, under the constraint InstanceContext <= P if InstanceCon...

static bool IsMicrosoftUsingDeclarationAccessBug(Sema &S, SourceLocation AccessLoc, AccessTarget &Entity)

MSVC has a bug where if during an using declaration name lookup, the declaration found is unaccessibl...

static CXXBasePath * FindBestPath(Sema &S, const EffectiveContext &EC, AccessTarget &Target, AccessSpecifier FinalAccess, CXXBasePaths &Paths)

Finds the best path from the naming class to the declaring class, taking friend declarations into acc...

static AccessResult IsAccessible(Sema &S, const EffectiveContext &EC, AccessTarget &Entity)

Determines whether the accessed entity is accessible.

static AccessResult HasAccess(Sema &S, const EffectiveContext &EC, const CXXRecordDecl *NamingClass, AccessSpecifier Access, const AccessTarget &Target)

static bool MightInstantiateTo(const CXXRecordDecl *From, const CXXRecordDecl *To)

Checks whether one class might instantiate to the other.

static void DiagnoseAccessPath(Sema &S, const EffectiveContext &EC, AccessTarget &entity)

Diagnose the path which caused the given declaration or base class to become inaccessible.

static CXXRecordDecl * FindDeclaringClass(NamedDecl *D)

static AccessResult CheckEffectiveAccess(Sema &S, const EffectiveContext &EC, SourceLocation Loc, AccessTarget &Entity)

Checks access to an entity from the given effective context.

static void DelayDependentAccess(Sema &S, const EffectiveContext &EC, SourceLocation Loc, const AccessTarget &Entity)

Defines various enumerations that describe declaration and type specifiers.

static QualType getPointeeType(const MemRegion *R)

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

QualType getRecordType(const RecordDecl *Decl) const

CanQualType getCanonicalType(QualType T) const

Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...

QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const

Return the unique reference to the type for the specified type declaration.

Represents a path from a specific derived class (which is not represented as part of the path) to a p...

AccessSpecifier Access

The access along this inheritance path.

BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...

std::list< CXXBasePath >::iterator paths_iterator

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...

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.

AccessSpecifier getAccessSpecifier() const

Returns the access specifier for this base specifier.

Represents a C++ constructor within a class.

Represents a C++ destructor within a class.

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

const CXXRecordDecl * getParent() const

Return the parent of this method declaration, which is the class in which this method is defined.

Represents a C++ struct/union/class.

bool isLambda() const

Determine whether this class describes a lambda function object.

bool hasDefinition() const

CXXRecordDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

bool isDerivedFrom(const CXXRecordDecl *Base) const

Determine whether this class is derived from the class Base.

Qualifiers getQualifiers() const

Retrieve all qualifiers.

CanProxy< U > getAs() const

Retrieve a canonical type pointer with a different static type, upcasting or downcasting as needed.

Declaration of a class template.

ClassTemplateDecl * getCanonicalDecl() override

Retrieves the canonical declaration of this template.

A POD class for pairing a NamedDecl* with an access specifier.

static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)

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

DeclContext * getParent()

getParent - Returns the containing DeclContext.

bool isFileContext() const

bool isDependentContext() const

Determines whether this context is dependent on a template parameter.

DeclContext * getPrimaryContext()

getPrimaryContext - There may be many different declarations of the same entity (including forward de...

decl_range decls() const

decls_begin/decls_end - Iterate over the declarations stored in this context.

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

Decl * getPreviousDecl()

Retrieve the previous declaration that declares the same entity as this declaration,...

virtual bool isOutOfLine() const

Determine whether this declaration is declared out of line (outside its semantic context).

FunctionDecl * getAsFunction() LLVM_READONLY

Returns the function itself, or the templated function if this is a function template.

bool isInvalidDecl() const

bool isLocalExternDecl() const

Determine whether this is a block-scope declaration with linkage.

void setAccess(AccessSpecifier AS)

SourceLocation getLocation() const

DeclContext * getDeclContext()

AccessSpecifier getAccess() const

DeclContext * getLexicalDeclContext()

getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).

virtual Decl * getCanonicalDecl()

Retrieves the "canonical" declaration of the given declaration.

The name of a declaration.

NestedNameSpecifier * getQualifier() const

Retrieve the nested-name-specifier that qualifies the name of this declaration, if it was present in ...

NestedNameSpecifierLoc getQualifierLoc() const

Retrieve the nested-name-specifier (with source-location information) that qualifies the name of this...

A dependently-generated diagnostic.

NamedDecl * getAccessNamingClass() const

QualType getAccessBaseObjectType() const

bool isAccessToMember() const

NamedDecl * getAccessTarget() const

SourceLocation getAccessLoc() const

const PartialDiagnostic & getDiagnostic() const

static DependentDiagnostic * Create(ASTContext &Context, DeclContext *Parent, AccessNonce _, SourceLocation Loc, bool IsMemberAccess, AccessSpecifier AS, NamedDecl *TargetDecl, CXXRecordDecl *NamingClass, QualType BaseObjectType, const PartialDiagnostic &PDiag)

AccessSpecifier getAccess() const

This represents one expression.

Represents a member of a struct/union/class.

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

bool isUnsupportedFriend() const

Determines if this friend kind is unsupported.

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.

DeclarationNameInfo getNameInfo() const

Represents a prototype with parameter type info, e.g.

Declaration of a template function.

FunctionTemplateDecl * getCanonicalDecl() override

Retrieves the canonical declaration of this template.

Describes an entity that is being initialized.

EntityKind getKind() const

Determine the kind of initialization.

QualType getType() const

Retrieve type being initialized.

ValueDecl * getDecl() const

Retrieve the variable, parameter, or field being initialized.

const InitializedEntity * getParent() const

Retrieve the parent of the entity being initialized, when the initialization itself is occurring with...

bool isInheritedVirtualBase() const

Return whether the base is an inherited virtual base.

@ EK_Member

The entity being initialized is a non-static data member subobject.

@ EK_Base

The entity being initialized is a base member subobject.

@ EK_ParenAggInitMember

The entity being initialized is a non-static data member subobject of an object initialized via paren...

@ EK_Delegating

The initialization is being done by a delegating constructor.

@ EK_LambdaCapture

The entity being initialized is the field that captures a variable in a lambda.

StringRef getCapturedVarName() const

For a lambda capture, return the capture's name.

const CXXBaseSpecifier * getBaseSpecifier() const

Retrieve the base specifier.

The injected class name of a C++ class template or class template partial specialization.

Represents the results of name lookup.

SourceLocation getNameLoc() const

Gets the location of the identifier.

CXXRecordDecl * getNamingClass() const

Returns the 'naming class' for this lookup, i.e.

QualType getBaseObjectType() const

Returns the base object type associated with this lookup; important for [class.protected].

Data structure that captures multiple levels of template argument lists for use in template instantia...

This represents a decl that may have a name.

NamedDecl * getUnderlyingDecl()

Looks through UsingDecls and ObjCCompatibleAliasDecls for the underlying named decl.

DeclarationName getDeclName() const

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

std::string getQualifiedNameAsString() const

SourceRange getSourceRange() const LLVM_READONLY

Retrieve the source range covering the entirety of this nested-name-specifier.

ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration.

ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...

Represents an ObjC class declaration.

bool isSuperClassOf(const ObjCInterfaceDecl *I) const

isSuperClassOf - Return true if this class is the specified class or is a super class of the specifie...

ObjCIvarDecl - Represents an ObjC instance variable.

ObjCMethodDecl - Represents an instance or class method declaration.

A reference to an overloaded function set, either an UnresolvedLookupExpr or an UnresolvedMemberExpr.

static FindResult find(Expr *E)

Finds the overloaded expression in the given expression E of OverloadTy.

SourceLocation getNameLoc() const

Gets the location of the name.

CXXRecordDecl * getNamingClass()

Gets the naming class of this lookup, if any.

PointerType - C99 6.7.5.1 - Pointer Declarators.

A (possibly-)qualified type.

bool isNull() const

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

bool isAnonymousStructOrUnion() const

Whether this is an anonymous struct or union.

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...

RecordDecl * getDecl() const

Scope - A scope is a transient data structure that is used while parsing the program.

bool isFriendScope() const

Determine whether this scope is a friend scope.

const Scope * getParent() const

getParent - Return the scope that this is nested in.

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)

Emit a diagnostic.

PartialDiagnostic PDiag(unsigned DiagID=0)

Build a partial diagnostic.

bool shouldDelayDiagnostics()

Determines whether diagnostics should be delayed.

void add(const sema::DelayedDiagnostic &diag)

Adds a delayed diagnostic.

Sema - This implements semantic analysis and AST building for C.

Scope * getCurScope() const

Retrieve the parser's current scope.

CXXSpecialMemberKind getSpecialMember(const CXXMethodDecl *MD)

bool SetMemberAccessSpecifier(NamedDecl *MemberDecl, NamedDecl *PrevMemberDecl, AccessSpecifier LexicalAS)

SetMemberAccessSpecifier - Set the access specifier of a member.

NamedDecl * FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, bool FindingInstantiatedContext=false)

Find the instantiation of the given declaration within the current instantiation.

AccessResult CheckFriendAccess(NamedDecl *D)

Checks access to the target of a friend declaration.

class clang::Sema::DelayedDiagnostics DelayedDiagnostics

bool isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass, DeclAccessPair Found, QualType ObjectType, SourceLocation Loc, const PartialDiagnostic &Diag)

Is the given member accessible for the purposes of deciding whether to define a special member functi...

FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const

Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...

AccessResult CheckDestructorAccess(SourceLocation Loc, CXXDestructorDecl *Dtor, const PartialDiagnostic &PDiag, QualType objectType=QualType())

TypeSourceInfo * SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, SourceLocation Loc, DeclarationName Entity, bool AllowDeducedTST=false)

Perform substitution on the type T with a given set of template arguments.

AccessResult CheckAllocationAccess(SourceLocation OperatorLoc, SourceRange PlacementRange, CXXRecordDecl *NamingClass, DeclAccessPair FoundDecl, bool Diagnose=true)

Checks access to an overloaded operator new or delete.

AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, const SourceRange &, DeclAccessPair FoundDecl)

ObjCMethodDecl * getCurMethodDecl()

getCurMethodDecl - If inside of a method body, this returns a pointer to the method decl for the meth...

void HandleDependentAccessCheck(const DependentDiagnostic &DD, const MultiLevelTemplateArgumentList &TemplateArgs)

const LangOptions & getLangOpts() const

AccessResult CheckStructuredBindingMemberAccess(SourceLocation UseLoc, CXXRecordDecl *DecomposedClass, DeclAccessPair Field)

Checks implicit access to a member in a structured binding.

AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, unsigned DiagID, bool ForceCheck=false, bool ForceUnprivileged=false)

Checks access for a hierarchy conversion.

AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, DeclAccessPair FoundDecl)

Perform access-control checking on a previously-unresolved member access which has now been resolved ...

bool IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *NamingClass, QualType BaseType)

Checks access to Target from the given class.

DeclContext * CurContext

CurContext - This is the current declaration context of parsing.

AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, DeclAccessPair FoundDecl, const InitializedEntity &Entity, bool IsCopyBindingRefToTemp=false)

Checks access to a constructor.

AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr, DeclAccessPair FoundDecl)

DeclContext * computeDeclContext(QualType T)

Compute the DeclContext that is associated with the given type.

void CheckLookupAccess(const LookupResult &R)

Checks access to all the declarations in the given result set.

AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, DeclAccessPair FoundDecl)

AccessResult CheckMemberAccess(SourceLocation UseLoc, CXXRecordDecl *NamingClass, DeclAccessPair Found)

Checks access to a member.

void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx)

@ Diagnose

Diagnose issues that are non-constant or that are extensions.

Encodes a location in the source.

A trivial tuple used to represent a source range.

SourceLocation getBegin() const

SourceRange getSourceRange() const LLVM_READONLY

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

Represents the declaration of a struct/union/class/enum.

The base class of all kinds of template declarations (e.g., class, function, etc.).

A container of type source information.

CanQualType getCanonicalTypeUnqualified() const

const T * castAs() const

Member-template castAs.

bool isDependentType() const

Whether this type is a dependent type, meaning that its definition somehow depends on a template para...

const T * getAs() const

Member-template getAs'.

Base class for declarations which introduce a typedef-name.

A reference to a name which we were able to look up during parsing but could not resolve to a specifi...

Represents a C++ member access expression for which lookup produced a set of overloaded functions.

The iterator over UnresolvedSets.

Represents a C++ using-declaration.

Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...

Represents a variable declaration or definition.

A declaration being accessed, together with information about how it was accessed.

A diagnostic message which has been conditionally emitted pending the complete parsing of the current...

AccessedEntity & getAccessData()

static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity)

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

void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)

const FunctionProtoType * T

bool declaresSameEntity(const Decl *D1, const Decl *D2)

Determine whether two declarations declare the same entity.

@ Class

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

AccessSpecifier

A C++ access specifier (public, private, protected), plus the special value "none" which means differ...

SourceRange getSourceRange() const LLVM_READONLY

getSourceRange - The range of the declaration name.

OverloadExpr * Expression