@@ -624,8 +624,8 @@ namespace {
624
624
// classes, one of its base classes.
625
625
class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
626
626
public:
627
- explicit RecordMemberExprValidatorCCC (const RecordType * RTy)
628
- : Record(RTy->getDecl ()) {
627
+ explicit RecordMemberExprValidatorCCC (QualType RTy)
628
+ : Record(RTy->getAsRecordDecl ()) {
629
629
// Don't add bare keywords to the consumer since they will always fail
630
630
// validation by virtue of not being associated with any decls.
631
631
WantTypeSpecifiers = false ;
@@ -671,33 +671,55 @@ class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback {
671
671
672
672
static bool LookupMemberExprInRecord (Sema &SemaRef, LookupResult &R,
673
673
Expr *BaseExpr,
674
- const RecordType * RTy,
674
+ QualType RTy,
675
675
SourceLocation OpLoc, bool IsArrow,
676
676
CXXScopeSpec &SS, bool HasTemplateArgs,
677
677
SourceLocation TemplateKWLoc,
678
678
TypoExpr *&TE) {
679
+ RecordDecl *RDecl = RTy->getAsRecordDecl ();
680
+ DeclContext *DC = SemaRef.computeDeclContext (RTy);
681
+ // If the object expression is dependent and isn't the current instantiation,
682
+ // lookup will not find anything and we must defer until instantiation.
683
+ if (!DC) {
684
+ R.setNotFoundInCurrentInstantiation ();
685
+ return false ;
686
+ }
687
+
688
+ // FIXME: Should this use Name.isDependentName()?
689
+ if (DeclarationName Name = R.getLookupName ();
690
+ Name.getNameKind () == DeclarationName::CXXConversionFunctionName &&
691
+ Name.getCXXNameType ()->isDependentType ()) {
692
+ R.setNotFoundInCurrentInstantiation ();
693
+ return false ;
694
+ }
695
+
679
696
SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange () : SourceRange ();
680
- RecordDecl *RDecl = RTy->getDecl ();
681
- if ( !SemaRef.isThisOutsideMemberFunctionBody (QualType ( RTy, 0 ) ) &&
682
- SemaRef.RequireCompleteType (OpLoc, QualType ( RTy, 0 ) ,
697
+ if (! RTy->isDependentType () &&
698
+ !SemaRef.isThisOutsideMemberFunctionBody (RTy) &&
699
+ SemaRef.RequireCompleteType (OpLoc, RTy,
683
700
diag::err_typecheck_incomplete_tag,
684
701
BaseRange))
685
702
return true ;
686
703
687
704
if (HasTemplateArgs || TemplateKWLoc.isValid ()) {
688
705
// LookupTemplateName doesn't expect these both to exist simultaneously.
689
- QualType ObjectType = SS.isSet () ? QualType () : QualType ( RTy, 0 ) ;
706
+ QualType ObjectType = SS.isSet () ? QualType () : RTy;
690
707
691
708
bool MOUS;
692
709
return SemaRef.LookupTemplateName (R, nullptr , SS, ObjectType, false , MOUS,
693
710
TemplateKWLoc);
694
711
}
695
712
696
- DeclContext *DC = RDecl;
697
713
if (SS.isSet ()) {
698
714
// If the member name was a qualified-id, look into the
699
715
// nested-name-specifier.
700
716
DC = SemaRef.computeDeclContext (SS, false );
717
+ // We tried to look into a dependent context that is not the current
718
+ // instantiation. Defer lookup until instantiation.
719
+ if (!DC) {
720
+ R.setNotFoundInCurrentInstantiation ();
721
+ return false ;
722
+ }
701
723
702
724
if (SemaRef.RequireCompleteDeclContext (SS, DC)) {
703
725
SemaRef.Diag (SS.getRange ().getEnd (), diag::err_typecheck_incomplete_tag)
@@ -717,7 +739,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
717
739
// The record definition is complete, now look up the member.
718
740
SemaRef.LookupQualifiedName (R, DC, SS);
719
741
720
- if (!R.empty ())
742
+ if (!R.empty () || R. wasNotFoundInCurrentInstantiation () )
721
743
return false ;
722
744
723
745
DeclarationName Typo = R.getLookupName ();
@@ -781,13 +803,15 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
781
803
const TemplateArgumentListInfo *TemplateArgs,
782
804
const Scope *S,
783
805
ActOnMemberAccessExtraArgs *ExtraArgs) {
806
+ #if 0
784
807
if (BaseType->isDependentType() ||
785
808
(SS.isSet() && isDependentScopeSpecifier(SS)) ||
786
809
NameInfo.getName().isDependentName())
787
810
return ActOnDependentMemberExpr(Base, BaseType,
788
811
IsArrow, OpLoc,
789
812
SS, TemplateKWLoc, FirstQualifierInScope,
790
813
NameInfo, TemplateArgs);
814
+ #endif
791
815
792
816
LookupResult R (*this , NameInfo, LookupMemberName);
793
817
@@ -797,7 +821,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType,
797
821
QualType RecordTy = BaseType;
798
822
if (IsArrow) RecordTy = RecordTy->castAs <PointerType>()->getPointeeType ();
799
823
if (LookupMemberExprInRecord (
800
- *this , R, nullptr , RecordTy-> castAs <RecordType>() , OpLoc, IsArrow,
824
+ *this , R, nullptr , RecordTy, OpLoc, IsArrow,
801
825
SS, TemplateArgs != nullptr , TemplateKWLoc, TE))
802
826
return ExprError ();
803
827
if (TE)
@@ -990,6 +1014,14 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
990
1014
const Scope *S,
991
1015
bool SuppressQualifierCheck,
992
1016
ActOnMemberAccessExtraArgs *ExtraArgs) {
1017
+
1018
+ if (R.wasNotFoundInCurrentInstantiation () || (SS.isValid () && !computeDeclContext (SS, false ))) {
1019
+ return ActOnDependentMemberExpr (BaseExpr, BaseExprType,
1020
+ IsArrow, OpLoc,
1021
+ SS, TemplateKWLoc, FirstQualifierInScope,
1022
+ R.getLookupNameInfo (), TemplateArgs);
1023
+ }
1024
+
993
1025
QualType BaseType = BaseExprType;
994
1026
if (IsArrow) {
995
1027
assert (BaseType->isPointerType ());
@@ -1028,11 +1060,11 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
1028
1060
// Rederive where we looked up.
1029
1061
DeclContext *DC = (SS.isSet ()
1030
1062
? computeDeclContext (SS, false )
1031
- : BaseType->castAs <RecordType>()-> getDecl ());
1063
+ : BaseType->getAsRecordDecl ());
1032
1064
1033
1065
if (ExtraArgs) {
1034
1066
ExprResult RetryExpr;
1035
- if (!IsArrow && BaseExpr) {
1067
+ if (!IsArrow && BaseExpr && !BaseExpr-> isTypeDependent () ) {
1036
1068
SFINAETrap Trap (*this , true );
1037
1069
ParsedType ObjectType;
1038
1070
bool MayBePseudoDestructor = false ;
@@ -1055,9 +1087,16 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
1055
1087
}
1056
1088
}
1057
1089
1058
- Diag (R.getNameLoc (), diag::err_no_member)
1059
- << MemberName << DC
1060
- << (BaseExpr ? BaseExpr->getSourceRange () : SourceRange ());
1090
+ if (DC) {
1091
+ Diag (R.getNameLoc (), diag::err_no_member)
1092
+ << MemberName << DC
1093
+ << (BaseExpr ? BaseExpr->getSourceRange () : SourceRange ());
1094
+ } else {
1095
+ // FIXME: Is this needed?
1096
+ Diag (R.getNameLoc (), diag::err_no_member)
1097
+ << MemberName << BaseExprType
1098
+ << (BaseExpr ? BaseExpr->getSourceRange () : SourceRange ());
1099
+ }
1061
1100
return ExprError ();
1062
1101
}
1063
1102
@@ -1287,7 +1326,10 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
1287
1326
return ExprError ();
1288
1327
1289
1328
QualType BaseType = BaseExpr.get ()->getType ();
1329
+
1330
+ #if 0
1290
1331
assert(!BaseType->isDependentType());
1332
+ #endif
1291
1333
1292
1334
DeclarationName MemberName = R.getLookupName ();
1293
1335
SourceLocation MemberLoc = R.getNameLoc ();
@@ -1299,29 +1341,32 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
1299
1341
if (IsArrow) {
1300
1342
if (const PointerType *Ptr = BaseType->getAs <PointerType>())
1301
1343
BaseType = Ptr->getPointeeType ();
1302
- else if (const ObjCObjectPointerType *Ptr
1344
+ else if (!BaseType->isDependentType ()) {
1345
+ if (const ObjCObjectPointerType *Ptr
1303
1346
= BaseType->getAs <ObjCObjectPointerType>())
1304
1347
BaseType = Ptr->getPointeeType ();
1305
- else if (BaseType->isRecordType ()) {
1306
- // Recover from arrow accesses to records, e.g.:
1307
- // struct MyRecord foo;
1308
- // foo->bar
1309
- // This is actually well-formed in C++ if MyRecord has an
1310
- // overloaded operator->, but that should have been dealt with
1311
- // by now--or a diagnostic message already issued if a problem
1312
- // was encountered while looking for the overloaded operator->.
1313
- if (!S.getLangOpts ().CPlusPlus ) {
1314
- S.Diag (OpLoc, diag::err_typecheck_member_reference_suggestion)
1315
- << BaseType << int (IsArrow) << BaseExpr.get ()->getSourceRange ()
1316
- << FixItHint::CreateReplacement (OpLoc, " ." );
1348
+ else if (BaseType->isRecordType ()) {
1349
+ // Recover from arrow accesses to records, e.g.:
1350
+ // struct MyRecord foo;
1351
+ // foo->bar
1352
+ // This is actually well-formed in C++ if MyRecord has an
1353
+ // overloaded operator->, but that should have been dealt with
1354
+ // by now--or a diagnostic message already issued if a problem
1355
+ // was encountered while looking for the overloaded operator->.
1356
+ if (!S.getLangOpts ().CPlusPlus ) {
1357
+ S.Diag (OpLoc, diag::err_typecheck_member_reference_suggestion)
1358
+ << BaseType << int (IsArrow) << BaseExpr.get ()->getSourceRange ()
1359
+ << FixItHint::CreateReplacement (OpLoc, " ." );
1360
+ }
1361
+ IsArrow = false ;
1362
+ } else if (BaseType->isFunctionType ()) {
1363
+ goto fail;
1364
+ } else {
1365
+ S.Diag (MemberLoc, diag::err_typecheck_member_reference_arrow)
1366
+ << BaseType << BaseExpr.get ()->getSourceRange ();
1367
+ return ExprError ();
1317
1368
}
1318
- IsArrow = false ;
1319
- } else if (BaseType->isFunctionType ()) {
1320
- goto fail;
1321
- } else {
1322
- S.Diag (MemberLoc, diag::err_typecheck_member_reference_arrow)
1323
- << BaseType << BaseExpr.get ()->getSourceRange ();
1324
- return ExprError ();
1369
+
1325
1370
}
1326
1371
}
1327
1372
@@ -1341,9 +1386,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R,
1341
1386
}
1342
1387
1343
1388
// Handle field access to simple records.
1344
- if (const RecordType *RTy = BaseType->getAs <RecordType> ()) {
1389
+ if (BaseType-> getAsRecordDecl () || BaseType->isDependentType ()) {
1345
1390
TypoExpr *TE = nullptr ;
1346
- if (LookupMemberExprInRecord (S, R, BaseExpr.get (), RTy , OpLoc, IsArrow, SS,
1391
+ if (LookupMemberExprInRecord (S, R, BaseExpr.get (), BaseType , OpLoc, IsArrow, SS,
1347
1392
HasTemplateArgs, TemplateKWLoc, TE))
1348
1393
return ExprError ();
1349
1394
@@ -1781,12 +1826,14 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base,
1781
1826
if (Result.isInvalid ()) return ExprError ();
1782
1827
Base = Result.get ();
1783
1828
1829
+ #if 0
1784
1830
if (Base->getType()->isDependentType() || Name.isDependentName() ||
1785
1831
isDependentScopeSpecifier(SS)) {
1786
1832
return ActOnDependentMemberExpr(Base, Base->getType(), IsArrow, OpLoc, SS,
1787
1833
TemplateKWLoc, FirstQualifierInScope,
1788
1834
NameInfo, TemplateArgs);
1789
1835
}
1836
+ #endif
1790
1837
1791
1838
ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl};
1792
1839
ExprResult Res = BuildMemberReferenceExpr (
0 commit comments