More warnings regarding gsl::Pointer and gsl::Owner attributes

Differential Revision: https://reviews.llvm.org/D65120

llvm-svn: 368446
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 693d759..4450497 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -6564,6 +6564,25 @@
   return false;
 }
 
+static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
+  if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
+    if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
+      return true;
+  if (!Callee->getParent()->isInStdNamespace() || !Callee->getIdentifier())
+    return false;
+  if (!isRecordWithAttr<PointerAttr>(Callee->getThisObjectType()) &&
+      !isRecordWithAttr<OwnerAttr>(Callee->getThisObjectType()))
+    return false;
+  if (!isRecordWithAttr<PointerAttr>(Callee->getReturnType()) &&
+      !Callee->getReturnType()->isPointerType())
+    return false;
+  return llvm::StringSwitch<bool>(Callee->getName())
+      .Cases("begin", "rbegin", "cbegin", "crbegin", true)
+      .Cases("end", "rend", "cend", "crend", true)
+      .Cases("c_str", "data", "get", true)
+      .Default(false);
+}
+
 static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
                                     LocalVisitor Visit) {
   auto VisitPointerArg = [&](const Decl *D, Expr *Arg) {
@@ -6577,10 +6596,9 @@
   };
 
   if (auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
-    const FunctionDecl *Callee = MCE->getDirectCallee();
-    if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
-      if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
-        VisitPointerArg(Callee, MCE->getImplicitObjectArgument());
+    const auto *MD = cast_or_null<CXXMethodDecl>(MCE->getDirectCallee());
+    if (MD && shouldTrackImplicitObjectArg(MD))
+      VisitPointerArg(MD, MCE->getImplicitObjectArgument());
     return;
   }