diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -381,6 +381,12 @@
   /// The type for the C ucontext_t type.
   TypeDecl *ucontext_tDecl = nullptr;
 
+  /// The type for the C pthread_t type.
+  TypeDecl *pthread_tDecl = nullptr;
+
+  /// The type for the C pthread_attr_t type.
+  TypeDecl *pthread_attr_tDecl = nullptr;
+
   /// Type for the Block descriptor for Blocks CodeGen.
   ///
   /// Since this is only used for generation of debug info, it is not
@@ -1789,6 +1795,30 @@
     return QualType();
   }
 
+  /// Set the type for the C pthread_t type.
+  void setpthread_tDecl(TypeDecl *pthread_tDecl) {
+    this->pthread_tDecl = pthread_tDecl;
+  }
+
+  /// Retrieve the C pthread_t type.
+  QualType getpthread_tType() const {
+    if (pthread_tDecl)
+      return getTypeDeclType(pthread_tDecl);
+    return QualType();
+  }
+
+  /// Set the type for the C pthread_attr_t type.
+  void setpthread_attr_tDecl(TypeDecl *pthread_attr_tDecl) {
+    this->pthread_attr_tDecl = pthread_attr_tDecl;
+  }
+
+  /// Retrieve the C pthread_attr_t type.
+  QualType getpthread_attr_tType() const {
+    if (pthread_attr_tDecl)
+      return getTypeDeclType(pthread_attr_tDecl);
+    return QualType();
+  }
+
   /// The result type of logical operations, '<', '>', '!=', etc.
   QualType getLogicalOperationType() const {
     return getLangOpts().CPlusPlus ? BoolTy : IntTy;
@@ -2022,7 +2052,10 @@
     GE_Missing_setjmp,
 
     /// Missing a type from <ucontext.h>
-    GE_Missing_ucontext
+    GE_Missing_ucontext,
+
+    /// Missing a type from <pthread.h>
+    GE_Missing_pthread
   };
 
   /// Return the type for the specified builtin.
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -44,6 +44,9 @@
 //  SJ -> sigjmp_buf
 //  K -> ucontext_t
 //  p -> pid_t
+//  Q -> pthread_t
+//  SQ -> pthread_attr_t
+//  (T) -> function with type T parsed recursively
 //  . -> "...".  This may only occur at the end of the function list.
 //
 // Types may be prefixed with the following modifiers:
@@ -998,7 +1001,7 @@
 LIBBUILTIN(_exit, "vi",           "fr",    "unistd.h", ALL_GNU_LANGUAGES)
 LIBBUILTIN(vfork, "p",            "fj",    "unistd.h", ALL_LANGUAGES)
 // POSIX pthread.h
-LIBBUILTIN(pthread_create, "",  "fC<2,3>", "pthread.h", ALL_GNU_LANGUAGES)
+LIBBUILTIN(pthread_create, "iQ*SQC*(v*v*)*v*",  "fC<2,3>", "pthread.h", ALL_GNU_LANGUAGES)
 
 // POSIX setjmp.h
 
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1210,7 +1210,13 @@
       SPECIAL_TYPE_OBJC_SEL_REDEFINITION       = 6,
 
       /// C ucontext_t typedef type
-      SPECIAL_TYPE_UCONTEXT_T                  = 7
+      SPECIAL_TYPE_UCONTEXT_T                  = 7,
+
+      /// C pthread_t typedef type
+      SPECIAL_TYPE_PTHREAD_T                   = 8,
+
+      /// C pthread_attr_t typedef type
+      SPECIAL_TYPE_PTHREAD_ATTR_T              = 9
     };
 
     /// The number of special type IDs.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -9383,6 +9383,11 @@
 //                          Builtin Type Computation
 //===----------------------------------------------------------------------===//
 
+static QualType DecodeFunctionTypeFromStr(
+    const char *&TypeStr, bool IsNested, bool IsNoReturn, bool IsNoThrow,
+    bool ForceEmptyTy, const ASTContext &Context,
+    ASTContext::GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs);
+
 /// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the
 /// pointer over the consumed characters.  This returns the resultant type.  If
 /// AllowTypeModifiers is false then modifier like * are not parsed, just basic
@@ -9657,6 +9662,24 @@
   case 'p':
     Type = Context.getProcessIDType();
     break;
+  case 'Q':
+    if (Signed)
+      Type = Context.getpthread_attr_tType();
+    else
+      Type = Context.getpthread_tType();
+
+    if (Type.isNull()) {
+      Error = ASTContext::GE_Missing_pthread;
+      return {};
+    }
+    break;
+  case '(':
+    Type = DecodeFunctionTypeFromStr(
+        Str, /*IsNested=*/true, /*IsNoReturn=*/false,
+        /*IsNoThrow=*/false, /*ForceEmptyTy=*/false, Context, Error, nullptr);
+    assert(Str[0] == ')' && "unmatched '('");
+    Str++;
+    break;
   }
 
   // If there are modifiers and if we're allowed to parse them, go for it.
@@ -9702,30 +9725,36 @@
   return Type;
 }
 
-/// GetBuiltinType - Return the type for the specified builtin.
-QualType ASTContext::GetBuiltinType(unsigned Id,
-                                    GetBuiltinTypeError &Error,
-                                    unsigned *IntegerConstantArgs) const {
-  const char *TypeStr = BuiltinInfo.getTypeString(Id);
+/// DecodeFunctionTypeFromStr - This decodes the entire type descriptor
+static QualType DecodeFunctionTypeFromStr(
+    const char *&TypeStr, bool IsNested, bool IsNoReturn, bool IsNoThrow,
+    bool ForceEmptyTy, const ASTContext &Context,
+    ASTContext::GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs) {
   if (TypeStr[0] == '\0') {
-    Error = GE_Missing_type;
+    Error = ASTContext::GE_Missing_type;
+    return {};
+  }
+
+  if (TypeStr[0] == ')') {
+    assert(IsNested && "unmatched ')' found at end of type list");
+    Error = ASTContext::GE_Missing_type;
     return {};
   }
 
   SmallVector<QualType, 8> ArgTypes;
 
   bool RequiresICE = false;
-  Error = GE_None;
-  QualType ResType = DecodeTypeFromStr(TypeStr, *this, Error,
-                                       RequiresICE, true);
-  if (Error != GE_None)
+  Error = ASTContext::GE_None;
+  QualType ResType =
+      DecodeTypeFromStr(TypeStr, Context, Error, RequiresICE, true);
+  if (Error != ASTContext::GE_None)
     return {};
 
-  assert(!RequiresICE && "Result of intrinsic cannot be required to be an ICE");
+  assert(!RequiresICE && "Result cannot be required to be an ICE");
 
-  while (TypeStr[0] && TypeStr[0] != '.') {
-    QualType Ty = DecodeTypeFromStr(TypeStr, *this, Error, RequiresICE, true);
-    if (Error != GE_None)
+  while (TypeStr[0] && TypeStr[0] != '.' && TypeStr[0] != ')') {
+    QualType Ty = DecodeTypeFromStr(TypeStr, Context, Error, RequiresICE, true);
+    if (Error != ASTContext::GE_None)
       return {};
 
     // If this argument is required to be an IntegerConstantExpression and the
@@ -9735,12 +9764,15 @@
 
     // Do array -> pointer decay.  The builtin should use the decayed type.
     if (Ty->isArrayType())
-      Ty = getArrayDecayedType(Ty);
+      Ty = Context.getArrayDecayedType(Ty);
 
     ArgTypes.push_back(Ty);
   }
 
-  if (Id == Builtin::BI__GetExceptionInfo)
+  assert((TypeStr[0] != ')' || IsNested) &&
+         "unmatched ')' found at end of type list");
+
+  if (ForceEmptyTy)
     return {};
 
   assert((TypeStr[0] != '.' || TypeStr[1] == 0) &&
@@ -9748,23 +9780,35 @@
 
   bool Variadic = (TypeStr[0] == '.');
 
-  FunctionType::ExtInfo EI(getDefaultCallingConvention(
+  FunctionType::ExtInfo EI(Context.getDefaultCallingConvention(
       Variadic, /*IsCXXMethod=*/false, /*IsBuiltin=*/true));
-  if (BuiltinInfo.isNoReturn(Id)) EI = EI.withNoReturn(true);
-
+  if (IsNoReturn)
+    EI = EI.withNoReturn(true);
 
   // We really shouldn't be making a no-proto type here.
-  if (ArgTypes.empty() && Variadic && !getLangOpts().CPlusPlus)
-    return getFunctionNoProtoType(ResType, EI);
+  if (ArgTypes.empty() && Variadic && !Context.getLangOpts().CPlusPlus)
+    return Context.getFunctionNoProtoType(ResType, EI);
 
   FunctionProtoType::ExtProtoInfo EPI;
   EPI.ExtInfo = EI;
   EPI.Variadic = Variadic;
-  if (getLangOpts().CPlusPlus && BuiltinInfo.isNoThrow(Id))
+  if (Context.getLangOpts().CPlusPlus && IsNoThrow)
     EPI.ExceptionSpec.Type =
-        getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone;
+        Context.getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone;
 
-  return getFunctionType(ResType, ArgTypes, EPI);
+  return Context.getFunctionType(ResType, ArgTypes, EPI);
+}
+
+/// GetBuiltinType - Return the type for the specified builtin.
+QualType ASTContext::GetBuiltinType(unsigned Id,
+                                    GetBuiltinTypeError &Error,
+                                    unsigned *IntegerConstantArgs) const {
+  const char *TypeStr = BuiltinInfo.getTypeString(Id);
+  return DecodeFunctionTypeFromStr(
+      TypeStr, /*IsNested=*/false, BuiltinInfo.isNoReturn(Id),
+      BuiltinInfo.isNoThrow(Id),
+      /*ForceEmptyTy=*/
+      Id == Builtin::BI__GetExceptionInfo, *this, Error, IntegerConstantArgs);
 }
 
 static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1968,6 +1968,8 @@
     return "setjmp.h";
   case ASTContext::GE_Missing_ucontext:
     return "ucontext.h";
+  case ASTContext::GE_Missing_pthread:
+    return "pthread.h";
   }
   llvm_unreachable("unhandled error kind");
 }
@@ -5970,6 +5972,10 @@
         Context.setsigjmp_bufDecl(NewTD);
       else if (II->isStr("ucontext_t"))
         Context.setucontext_tDecl(NewTD);
+      else if (II->isStr("pthread_t"))
+        Context.setpthread_tDecl(NewTD);
+      else if (II->isStr("pthread_attr_t"))
+        Context.setpthread_attr_tDecl(NewTD);
     }
 
   return NewTD;
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -4847,6 +4847,43 @@
         }
       }
     }
+
+    if (unsigned Pthread_t = SpecialTypes[SPECIAL_TYPE_PTHREAD_T]) {
+      QualType Pthread_tType = GetType(Pthread_t);
+      if (Pthread_tType.isNull()) {
+        Error("pthread_t type is NULL");
+        return;
+      }
+
+      if (!Context.pthread_tDecl) {
+        if (const TypedefType *Typedef = Pthread_tType->getAs<TypedefType>())
+          Context.setpthread_tDecl(Typedef->getDecl());
+        else {
+          const TagType *Tag = Pthread_tType->getAs<TagType>();
+          assert(Tag && "Invalid pthread_t type in AST file");
+          Context.setpthread_tDecl(Tag->getDecl());
+        }
+      }
+    }
+
+    if (unsigned Pthread_attr_t = SpecialTypes[SPECIAL_TYPE_PTHREAD_ATTR_T]) {
+      QualType Pthread_attr_tType = GetType(Pthread_attr_t);
+      if (Pthread_attr_tType.isNull()) {
+        Error("pthread_attr_t type is NULL");
+        return;
+      }
+
+      if (!Context.pthread_attr_tDecl) {
+        if (const TypedefType *Typedef =
+                Pthread_attr_tType->getAs<TypedefType>())
+          Context.setpthread_attr_tDecl(Typedef->getDecl());
+        else {
+          const TagType *Tag = Pthread_attr_tType->getAs<TagType>();
+          assert(Tag && "Invalid pthread_attr_t type in AST file");
+          Context.setpthread_attr_tDecl(Tag->getDecl());
+        }
+      }
+    }
   }
 
   ReadPragmaDiagnosticMappings(Context.getDiagnostics());
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4966,6 +4966,8 @@
   AddTypeRef(Context.ObjCClassRedefinitionType, SpecialTypes);
   AddTypeRef(Context.ObjCSelRedefinitionType, SpecialTypes);
   AddTypeRef(Context.getucontext_tType(), SpecialTypes);
+  AddTypeRef(Context.getpthread_tType(), SpecialTypes);
+  AddTypeRef(Context.getpthread_attr_tType(), SpecialTypes);
 
   if (Chain) {
     // Write the mapping information describing our module dependencies and how
diff --git a/clang/test/Sema/implicit-builtin-decl.c b/clang/test/Sema/implicit-builtin-decl.c
--- a/clang/test/Sema/implicit-builtin-decl.c
+++ b/clang/test/Sema/implicit-builtin-decl.c
@@ -68,4 +68,4 @@
 // CHECK:     ReturnsTwiceAttr {{.*}} <{{.*}}> Implicit
 
 // PR40692
-void pthread_create(); // no warning expected
+void pthread_create(); // expected-warning{{declaration of built-in function 'pthread_create' requires inclusion of the header <pthread.h>}}
diff --git a/clang/test/Sema/implicit-builtin-redecl.c b/clang/test/Sema/implicit-builtin-redecl.c
--- a/clang/test/Sema/implicit-builtin-redecl.c
+++ b/clang/test/Sema/implicit-builtin-redecl.c
@@ -24,3 +24,9 @@
 }
 
 typedef int rindex;
+
+// PR40692
+typedef void pthread_t;
+typedef void pthread_attr_t;
+int pthread_create(pthread_t *, const pthread_attr_t *, // no-warning
+                   void *(*)(void *), void *);