summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/Sema.h2
-rw-r--r--clang/lib/Sema/SemaAccess.cpp19
-rw-r--r--clang/lib/Sema/SemaInit.cpp44
-rw-r--r--clang/lib/Sema/SemaInit.h12
4 files changed, 60 insertions, 17 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 54d36357be2..1595941651f 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -2415,6 +2415,8 @@ public:
bool CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E,
NamedDecl *D,
AccessSpecifier Access);
+ bool CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D,
+ AccessSpecifier Access);
bool CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
NamedDecl *D, AccessSpecifier Access);
bool CheckAccess(const LookupResult &R, NamedDecl *D, AccessSpecifier Access);
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index 34c9718014c..ceee61df23a 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -306,7 +306,24 @@ bool Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
return false;
}
-/// Checks access to an overloaded member operator.
+/// Checks access to a constructor.
+bool Sema::CheckConstructorAccess(SourceLocation UseLoc,
+ CXXConstructorDecl *Constructor,
+ AccessSpecifier Access) {
+ if (!getLangOptions().AccessControl)
+ return false;
+
+ CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Constructor->getParent());
+
+ LookupResult R(*this, Constructor->getDeclName(), UseLoc, LookupOrdinaryName);
+ R.suppressDiagnostics();
+
+ R.setNamingClass(NamingClass);
+ return CheckAccess(R, Constructor, Access);
+}
+
+/// Checks access to an overloaded member operator, including
+/// conversion operators.
bool Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
Expr *ObjectExpr,
NamedDecl *MemberOperator,
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index db888a62a4f..4f23751e735 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -1971,7 +1971,8 @@ void InitializationSequence::AddAddressOverloadResolutionStep(
Step S;
S.Kind = SK_ResolveAddressOfOverloadedFunction;
S.Type = Function->getType();
- S.Function = Function;
+ // Access is currently ignored for these.
+ S.Function = DeclAccessPair::make(Function, AccessSpecifier(0));
Steps.push_back(S);
}
@@ -1992,11 +1993,12 @@ void InitializationSequence::AddReferenceBindingStep(QualType T,
}
void InitializationSequence::AddUserConversionStep(FunctionDecl *Function,
+ AccessSpecifier Access,
QualType T) {
Step S;
S.Kind = SK_UserConversion;
S.Type = T;
- S.Function = Function;
+ S.Function = DeclAccessPair::make(Function, Access);
Steps.push_back(S);
}
@@ -2029,11 +2031,12 @@ void InitializationSequence::AddListInitializationStep(QualType T) {
void
InitializationSequence::AddConstructorInitializationStep(
CXXConstructorDecl *Constructor,
+ AccessSpecifier Access,
QualType T) {
Step S;
S.Kind = SK_ConstructorInitialization;
S.Type = T;
- S.Function = Constructor;
+ S.Function = DeclAccessPair::make(Constructor, Access);
Steps.push_back(S);
}
@@ -2246,7 +2249,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
T2 = cv1T1;
// Add the user-defined conversion step.
- Sequence.AddUserConversionStep(Function, T2.getNonReferenceType());
+ Sequence.AddUserConversionStep(Function, Best->getAccess(),
+ T2.getNonReferenceType());
// Determine whether we need to perform derived-to-base or
// cv-qualification adjustments.
@@ -2577,10 +2581,11 @@ static void TryConstructorInitialization(Sema &S,
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
if (Kind.getKind() == InitializationKind::IK_Copy) {
- Sequence.AddUserConversionStep(Best->Function, DestType);
+ Sequence.AddUserConversionStep(Best->Function, Best->getAccess(), DestType);
} else {
Sequence.AddConstructorInitializationStep(
cast<CXXConstructorDecl>(Best->Function),
+ Best->getAccess(),
DestType);
}
}
@@ -2778,13 +2783,13 @@ static void TryUserDefinedConversion(Sema &S,
if (isa<CXXConstructorDecl>(Function)) {
// Add the user-defined conversion step. Any cv-qualification conversion is
// subsumed by the initialization.
- Sequence.AddUserConversionStep(Function, DestType);
+ Sequence.AddUserConversionStep(Function, Best->getAccess(), DestType);
return;
}
// Add the user-defined conversion step that calls the conversion function.
QualType ConvType = Function->getResultType().getNonReferenceType();
- Sequence.AddUserConversionStep(Function, ConvType);
+ Sequence.AddUserConversionStep(Function, Best->getAccess(), ConvType);
// If the conversion following the call to the conversion function is
// interesting, add it as a separate step.
@@ -3250,7 +3255,9 @@ InitializationSequence::Perform(Sema &S,
case SK_ResolveAddressOfOverloadedFunction:
// Overload resolution determined which function invoke; update the
// initializer to reflect that choice.
- CurInit = S.FixOverloadedFunctionReference(move(CurInit), Step->Function);
+ // Access control was done in overload resolution.
+ CurInit = S.FixOverloadedFunctionReference(move(CurInit),
+ cast<FunctionDecl>(Step->Function.getDecl()));
break;
case SK_CastDerivedToBaseRValue:
@@ -3329,13 +3336,14 @@ InitializationSequence::Perform(Sema &S,
// or a conversion function.
CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
bool IsCopy = false;
- if (CXXConstructorDecl *Constructor
- = dyn_cast<CXXConstructorDecl>(Step->Function)) {
+ FunctionDecl *Fn = cast<FunctionDecl>(Step->Function.getDecl());
+ AccessSpecifier FnAccess = Step->Function.getAccess();
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) {
// Build a call to the selected constructor.
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
SourceLocation Loc = CurInitExpr->getLocStart();
CurInit.release(); // Ownership transferred into MultiExprArg, below.
-
+
// Determine the arguments required to actually perform the constructor
// call.
if (S.CompleteConstructorCall(Constructor,
@@ -3350,6 +3358,8 @@ InitializationSequence::Perform(Sema &S,
move_arg(ConstructorArgs));
if (CurInit.isInvalid())
return S.ExprError();
+
+ S.CheckConstructorAccess(Kind.getLocation(), Constructor, FnAccess);
CastKind = CastExpr::CK_ConstructorConversion;
QualType Class = S.Context.getTypeDeclType(Constructor->getParent());
@@ -3358,8 +3368,11 @@ InitializationSequence::Perform(Sema &S,
IsCopy = true;
} else {
// Build a call to the conversion function.
- CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Step->Function);
+ CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn);
+ S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr,
+ Conversion, FnAccess);
+
// FIXME: Should we move this initialization into a separate
// derived-to-base conversion? I believe the answer is "no", because
// we don't want to turn off access control here for c-style casts.
@@ -3424,8 +3437,8 @@ InitializationSequence::Perform(Sema &S,
case SK_ConstructorInitialization: {
CXXConstructorDecl *Constructor
- = cast<CXXConstructorDecl>(Step->Function);
-
+ = cast<CXXConstructorDecl>(Step->Function.getDecl());
+
// Build a call to the selected constructor.
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
SourceLocation Loc = Kind.getLocation();
@@ -3444,6 +3457,9 @@ InitializationSequence::Perform(Sema &S,
Entity.getKind() == InitializedEntity::EK_Base);
if (CurInit.isInvalid())
return S.ExprError();
+
+ // Only check access if all of that succeeded.
+ S.CheckConstructorAccess(Loc, Constructor, Step->Function.getAccess());
bool Elidable
= cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable();
diff --git a/clang/lib/Sema/SemaInit.h b/clang/lib/Sema/SemaInit.h
index 001ba91d546..2b49df28fe8 100644
--- a/clang/lib/Sema/SemaInit.h
+++ b/clang/lib/Sema/SemaInit.h
@@ -15,6 +15,7 @@
#include "SemaOverload.h"
#include "clang/AST/Type.h"
+#include "clang/AST/UnresolvedSet.h"
#include "clang/Parse/Action.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -449,7 +450,11 @@ public:
/// \brief When Kind == SK_ResolvedOverloadedFunction or Kind ==
/// SK_UserConversion, the function that the expression should be
/// resolved to or the conversion function to call, respectively.
- FunctionDecl *Function;
+ ///
+ /// Always a FunctionDecl.
+ /// For conversion decls, the naming class is the source type.
+ /// For construct decls, the naming class is the target type.
+ DeclAccessPair Function;
/// \brief When Kind = SK_ConversionSequence, the implicit conversion
/// sequence
@@ -616,7 +621,9 @@ public:
/// \brief Add a new step invoking a conversion function, which is either
/// a constructor or a conversion function.
- void AddUserConversionStep(FunctionDecl *Function, QualType T);
+ void AddUserConversionStep(FunctionDecl *Function,
+ AccessSpecifier Access,
+ QualType T);
/// \brief Add a new step that performs a qualification conversion to the
/// given type.
@@ -631,6 +638,7 @@ public:
/// \brief Add a constructor-initialization step.
void AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
+ AccessSpecifier Access,
QualType T);
/// \brief Add a zero-initialization step.
OpenPOWER on IntegriCloud